树的遍历算法

树的先序遍历
typedef struct{/二叉树的链式存储结构
 elemtype data;
 btnode *lchild,*rchild;//左右孩子指针域
}btnode,*btree;

void visit(btnode *t){
 cout<<t->data<<endl;
}
递归
void preorder(btnode *t){//递归先序遍历
 while(t){
  visit(t);
  preorder(t->lcjild);//遍历左子树
  preorder(t->rchild);//遍历右子树
 }
}
非递归
void preorder(btnode *t){
 btnode *stack[max];
 int top=-1;
 btnode *p=t;
 while(p!=null){
  stack[++top]=p;//初始化。根入栈
  while(top>-1){//栈不空时循环
   p=stack[top--];//p指向栈顶元素
   visit(p);//访问栈顶元素
   if(p->rchild){stack[++top]=p->rchild;}//当前节点的有孩子入栈
   if(p->lcjild){stack[++top}=p->lchild;}//若左孩子不空,入栈左孩子
  }//while 
 }//while
}
void preorder(btnode *t){//非递归先序遍历
 btnode *stack[max];
 int top=0;
 btnode *p=t;
 do{
 while(p!=null){
  stack[top++]=p;
  visit(stack[top]);//访问栈顶元素
  p=p->lchild;
  }
 while(top>0){
  top--;
  p=stack[top];
  p=p->rchild;
  }
 }while(p!=null||top>0)
}
树的中序遍历
递归算法
void midorder(btnode *t){
while(t){
midorder(t->lchild);
visit(t);
midorder(t->rchild);}
}
非递归算法(入栈一直向左走,出栈访问右子树)
void midordedr(btnode *t){
//非递归
btnode* stack[max];
btnoder *p=t;//工作指针
top=0;//初始化栈
do{
while(p){
stack[top++]=p->lchild;
p=p->lchild;
}
while(top>0){
visit(stack[top--]);//访问栈顶元素并出栈栈顶元素
p=stack[top];
p=p->rchild;
}
}while(t!=null||top>0)
}
树的后序遍历
递归
void postorder(btnode *t){
 while(t){
 postorder(t->lchild);
 postorder(t->rchild);
 visit(t);
 }
}
非递归

算法思想:从根节点开始一直朝左遍历树,直至数的左子树为空,此时看树的右子树是否为空,若为空,则出栈栈顶元素并访问,top--,遍历指针重新指向栈顶元素,若是存在右子树并且当前右子树已经被访问过了,则出栈当前元素并访问,top--,遍历指针重新指向栈顶元素,若存在右子树并且尚未被访问过,遍历指针指向右子树并入栈,重复前面的步骤,直到栈空并且树被遍历完结束。

void postorder(btnode *t){
 btnode *stack[max];
 int top=-1;
 btnode *p=t;
 btnode *pre=NULL;
 bool visited=false;
 if(t){//树不空时进行遍历
 stack[++top]=t;//初始化栈顶元素
 while(top>-1){//栈不空时进行循环
  p=stack[top];
  if(p->lchild){//p的右子树若不空,一直入栈
   stack[++top]=p->lchild;}
 }else if(p->lchild==NULL || visited){//左子树为空或已经被访问过
   visited=false;
   if(p->rchild==NULL||(p-rchild!=NULL&&pre==p->rchild)){
    //右子树为空或者当前右子树已经被访问过了
    visit(p);//访问当前结点
    pre=p;//更新
    top--;
    visited=true;//已经被访问过的标记
   }else if(p-rchild && pre!=p->rchild){
    //右子树存在,并且当前的右子树尚未被访问过
    stack[++top]=p->rchild;//入栈右子树}
   }//if
 }/while
}

遍历算法的应用

1、求叶子
//方法一
int leaf(btnode *t) {
 while(t){
  if(t->lchild==NULL&&t->rchild==NULL){
   n++;
   return n;}
  leaf(t->lchild);
  leaf(t->rchild);
  }
}
//方法二
int leaf(btnode *t){
 int n;
 if(!t){
  n=0;
 }else if(t->lchild!=null||p->rchild!=null){
  n=leaf(t->lchild)+leaf(t->rchild)}
 else{
  n++;}
 return n;
 }
}
2、求树高

分别求左树的高和右数的高,再做比较

//方法一
void postbitreedepth(btnode *t){
 int hl,hr,max;
 if(t){
  postbitreedepth(t->lchild);//求左子树的深度
  postbitreedepth(t->rchild);//求右子树的深度
  max=hl>hr:hl?hr;
  return(max+1);//返回树的深度}
 else return(0);
}

//方法二
void postbitreedepth(btnode *t,int level,int &depth){
 /*t只想二叉树的根的指针,level是当前所指结点的层次,初始为1,depth是当前所求得的的最大数深度,开始为0*/
 if(t){
  if(level>depth) depth=level;
  postbitreedepth(t->lchild;level+1;depth);
  postbitreedepth(t->rcild;level+1;depth);
 }else return(0);

}
3、在二叉树上查找某个结点
bool locate(btnode *t,elemtype x,btnode *p){
 if(t==null) 
 {p=null;
  return false;}
 while(t){
 if(t->data==x) {
  p=t;
  return true;}
 if(locate(t->lchild)) {
  p=t->lchild;
  return true;}else return(locate(t->rchild));
 }
}
4、复制二叉树

算法思想:利用后序遍历的思想,先复制左右子树,再生成一个新的根节点。

//后序遍历复制二叉树
//复制二叉树
Bitree *gettreenode(elemtype i,BiTnode *l,BiTnode *r){
 //生成一个元素值为i,左指针为l,右指针r的结点
 T=new BiTnode;
 T->data=i;
 T->lchild=l;
 T-rchild=r; 
 return T;
}
BiTree copytree(BiTnode *T){
//复制二叉树T
 if(!T) return NULL;
 if(T->lchild)//复制左孩子
  {nl=newcopytree(T->lchild);}
 else nl=null;//否则左孩子为空
 if(T->rchild!=null){//复制右孩子
 nr=copytree(T->rchild);}
 else nr=null;//否则右孩子置空
 T=gettreenode(T->node,T->lchild,T->rchild);//生成根节点
 return T;
 }
}

树的层序遍历(队列)
void levelorder(BiTree t){
  Quequ Q;
  InitQueue(Q);//初始化一个队列
  BiTree p;//工作指针
  Enqueue(Q,t)//将根节点入队
  while(!isEmpty(Q)){//队列不空时
   Dequeue(Q,p)//出队队头元素给p
   visit(p);//访问p
   if(p->lchild!=null){//若左子树不空,入队
    Enqueue(Q,p->lchild);}
   if(p->rchild!=null){//ruo右子树不空,入队右子树
    Enqueue(Q,p);}
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值