二叉树的递归算法应用

本文探讨了二叉树的各种递归算法应用,包括:根据先序和中序序列构造二叉树、计算树的高度、度数统计、镜像操作、查找先序序列中的节点、满二叉树的先序后序序列关系、相似二叉树判断、二叉树线索化以及在中序线索二叉树中找后序前驱节点,以及叶节点的带权路径长度之和。每种操作都提供了详细的算法思路。

1.求叶节点个数(包含于4.)
2.由已知中序、先序序列建树
3.求高度
4.求度为1/2/0的节点个数
5.交换二叉树左右孩子(镜面反射二叉树)
6.查找先序序列中第k个节点
7.根据先序、后序确定满二叉树
8.判断两个二叉树是否相似
9.二叉树线索化
10.在中序线索二叉树里查找指定节点在后序的前驱节点
11.叶节点的带权路径长度之和

2.由已知中序、先序序列建树
算法思想:设先序序列为pre[],中序序列为mid[],先序序列第一个元素为根节点,在中序序列中找到根节点,左边为左子树,右边为右子树,求出左右子树的长度。更新序列首位,进行递归。

btree creatree(pre[],mid[],int f1,int r1,int f2,int r2){
//f1,r1为pre的先序序列首尾指针,f2,r2为中序序列mid的首尾指针
 int i;
 root=new btnode;
 root->data=pre[f1]->data;
 for(i=f2;pre[f1]!=mid[i];i++);//找到根节点在中序序列的位置
 len1=i-f2;//左子树长度
 len2=r2-i;//右子树长度
 if(len1) //左子树存在
  root->lchild=creatree(pre[],mid[],f1+1,f1+len1,f2,f2+len1-1);
 else root->lchild=null;
 if(len2)//右子树存在
  root->rchild=creatree(pre[],mid[],r1-len2+1,r1,r2-len2+1,r2);
 else root->rchild=null;
 return root;
}

3.求高度
算法思想:左右子树较高的高度+1(后序遍历)

int d;//全局变量
int depth(btree t){
 if(t==null) return 0;
 int dl,dr;
 dl=depth(t->lchild);
 dr=depth(t->rchild);
 d=dl>dr?dl:dr;
 return d;
}

或者:先序遍历。

void depth(btree t,int d,int level){
 //level当前层,d为深度
 if(level>d) d=level;
 depth(t,d,level+1);
 depth(t,d,level+1);
}

4.求度为0/1/2的节点个数

int num_degree(btree t,int degree){
 if(degree==0){
  if(t==null) return 0;
  if(t->lchild==null&&t->rchild==null)
   return 1+num_degree(t->lchild,0)+num_degree(t->rchild,0);
 }
 if(degree==1){
  if(t==null) return 0;
  if(t->lchild&&!t->rchild)
   return 1+num_degree(t->lchild,1);
  if(t->rchild&&!t->lchild)
   return 1+num_degree(t->rchild,1);
 }
 if(degree==2){
  if(t==null) return 0;
  if(t->lchild&&t->rchild)
   return 1+num_degree(t->lchild,2)+num_degree(t->rchild,2);
 }
}

5.镜面二叉树
算法思想:后序遍历。交换左右子树,再交换左右孩子

btree mirror_tree(btree t){
 if(t){
  mirror_tree(t->lchild);
  mirror_tree(t->rchild);
  btree temp;
  temp=t->lchild;
  t->lchild=t->rchild;
  t->rchild=temp;
 }
}

6.查找先序序列中第k个节点
算法思想:

int i=0;//全局变量
btree pre_k(btree t,int k){
 if(t){
   if(k==i) return t;
   i++;
   pre_k(t->lchild,k);
   pre_k(t->rchild,k);
 }
}

7.根据一满二叉树的先序序列,确定后序序列
算法思想:先序序列pre[],后序序列post[]。
对于满二叉树,任一节点的左右指数含有相等的节点数,同时,先序序列的第一个节点作为后序序列的最后一个节点,由此得到递归模型:
递归出口:r1< f1.
递归主体:
f(pre,f1,r1,post,f2,r2) :
post[r2]=pre[f1];
取中间位置half=(r1-f1);
对左子树递归 f(pre,f1+1,f1+half,post,f2,f2+half-1);
对右子树递归f(pre,f1+half+1,r1,post,f2+half,r2-1);

void pretopost(elemtype pre[],elemtype post[],int f1,int r1,int f2,int r2){
 if(r1<f1) return;
 post[r2]=pre[f1];
 int half=(r1-f1)/2;
 pretopost(pre,post,f1+1,f1+half,f2,f2+half-1);
 pretopost(pre,post,f1+half+1,r1,f2+half,r2-1);
}

8.判断两个二叉树是否相似
算法思想:先序

int similar(btree t1,btree t2){
 if(t1==t2==null) return 1;
 else if(t1==null||t2==null) return 0;
 else{
  return similar(t1->lchild,t2->lchild)*similar(t1->rchild,t2->rchild);
 }
}

9.二叉树线索化

//线索二叉树的结构:
typedef struct threadnode{
 elemtype data;
 struct threadnode *lchild,*rchild;
 int ltag,rtag;
}threadnode,*threadtree;
//中序线索化
void inthread(threadtree &p,threadtree &pre){
 if(p){
  inthread(p->lchild,pre);
  if(p->lcihld==null){//左指针为空
   p->lchild=pre;//指向前驱
   p->ltag=1;//标记
  }
  if(pre!=null&&p->rchild==null){//右指针为空且不是首个节点(pre为空)
   pre->rchild=p;//建立前驱节点的后继
   p->rtag=1;//标记
  }
 pre=p;//标记当前节点为刚访问过的节点
 inthread(p->rchlid,pre);
 }
}
//主程序
void creatinthread(threadtree t){
 threadtree pre=null;//初始化
 if(t){
  inthread(t,pre);
  pre->rchlid=null;
  pre->rtag=1;
 }
}
//求首节点
threadnode *firstnode(threadnode *p){
 while(p->ltag==0) p=p->lchild;
 return p;
}
//求后继
threadnode *nextnode(threadnode *p){
 if(p->rtag==0) return firstnode(p->rchild);
 else return p->rchild;
}
//非递归且不需要栈的遍历算法
void inorder(threadtree t){
 for(threadnode *p=firstnode(t);p!=null;p=nextnode(p))
  visit(p);
}

10.在中序线索二叉树里查找指定节点在后序的前驱节点

11.叶节点的带权路径长度之和

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值