二叉树的遍历

二叉树是 n个(n>=0)个结点的有限集合。当n=0时,称为空二叉树;当n>0时。该集合有一个根结点及两颗互不相交的,被称为左子树和右子树的二叉树组成(有点像递归定义)。也可以理解为:二叉树是满足一下两个条件的树(1)每个家结点的度不大于2,;(2)结点的子树位置是明确分左右的,不能随意改变。

     

二叉树的遍历在顺序上分为先序,中序和后序三种,而在方法上又分为递归和非递归两种,从结构上还有层次遍历;

(1)先序遍历二叉树的操作定义为:

若二叉树不空,则空操作,否则一次执行下列操作

访问根结点;按先序遍历左子树;按先序遍历右子树;

(2)中序遍历二叉树的操作定义为:

若二叉树不空,则空操作,否则一次执行下列操作

先按中序遍历左子树;访问根结点;再按中序遍历右子树;

(3)后序遍历二叉树的操作定义为:

若二叉树不空,则空操作,否则一次执行下列操作

先按后序遍历左子树;再按后序遍历右子树;最后访问根结点;


如图的二叉树的先中后序的遍历结果如下所示

先序:A、B、D、G、C、E、F

中序:B、G、D、A、E、C、F

后序:G、D、B、E、F、C、A

二叉树遍历的递归实现


先序遍历

</pre><pre name="code" class="cpp">void PerOrder(BiTree root)
{
     if(root){
         Visit(root);//访问根结点
         PreOrder(root->Lchild);//先序遍历左子树
         PreOrder(root->Rchild);//先序遍历右子树
     }
}
中序遍历

void Order_Travarsal_Tree(BiTree root)
{
     if(root){
         PreOrder(root->Lchild);//先序遍历左子树
         Visit(root);//访问根结点
         PreOrder(root->Rchild);//先序遍历右子树
     }
}
后序遍历

void PostOrder(BiTree root)
{
     if(root){
         PreOrder(root->Lchild);//先序遍历左子树
         PreOrder(root->Rchild);//先序遍历右子树
         Visit(root);//访问根结点
     }
}

二叉树的非递归遍历

1. 先序非递归的实现

(1)访问根结点,根结点入栈并进入左子树,进而访问左子树的根结点并入栈,在进入下层左子树,...... ,如此重复知道当前结点为空;

(2)若栈非空,则从栈顶退出上一层结点,并进入该节点的右子树。

重复上述(1)(2)步骤,知道当前结点及栈均为空,结束

void PreOrder( BiTree root)
{
    SeqStack *S;
    BiTree  p;
    InitStack(S); p=root;
    while(p!=NULL || !IsEmpty(S)){//当前节点和栈均为空,则结束
       while(p!=NULL){
           Visit(p->date); push(S,&p);//访问根结点,根指针入栈,进入左子树
       if(!IsEmpty(S)){
            Pop(S,&p); p=p->Rchild;//根指针退栈,进入右子树
         }
       }
    }
}
2.中序非递归的实现

(1)根结点入栈,进入其左子树,进而左子树的根结点入栈,进入下一层左子树,...... ,如此重复直到当前结点为空。

(2)若栈非空,从栈顶退出上一层的结点,访问出栈结点,并进入其右子树

重复上述(1)(2)步骤,直至当前结点及栈为空,结束

void Order_Travarsal_Tree( BiTree root)
{
    SeqStack *S;
    BiTree  p;
    InitStack(S); p=root;
    while(p!=NULL || !IsEmpty(S)){//当前节点和栈均为空,则结束
       while(p!=NULL){
            push(S,&p);p=p->Lchild;//根结点入栈,并进入左子树
        }
       if(!IsEmpty(S)){
            Pop(S,&p);Visit(p->date); p=p->Rchild;//根指针退栈,访问上一层子树,进入右子树
         }
    }
}

3.后序非递归实现

(1)当前结点入栈,并进入其左子树,重复至当前结点为空

(2)若栈非空,判断栈顶结点p的右子树是否为空、右子树是否访问过,是则退栈,访问p结点,p赋值给q,p置空;否则进入p的右子树;

void PostOrder(BiTree root)
{
   SeqStack *S;
   BiTree p,q;
   InitStack(S);
   p=root;
   q=NULL;
   while(p!=NULL || !IsEmpty(S)){
       while(p!=NULL){
           Push(p);p=p->Lchild;
       }
       if(!IsEmptyS)){
           Top(S,&p);
           if(p->Rchild == NULL || p->Rchild == q){//判断右子树为空或者刚才刚问过
              Pop(S,&p);
              Visit(p->date);
              p=q;
              p=NULL;
           }else
              p=p->Rchild;
       }
   }
}
二叉树的按层遍历

  二叉树的非递归遍历是用栈来实现的,而它的层遍历则是用队列来实现的,实现方式如下:

首先根结点入队,当队列非空时,重复如下两个步骤。

(1)队头结点出队,并访问对头结点。

(2)出队结点的非空左右子树一次入队。

void LevelOrder(BiTree root)
{
   SeqQueue *Q;
   BiTree p;
   InitQueue(Q);
   EnterQueue(Q,root);
   while(!Isempty(Q)){
       DeletQueue(Q,&p);
       Visit(p->date);
       if(p->Lchild != NULL)
          EnterQueue(Q,p->Lchild);
        if(p->Rchld != NULL)
          EnterQueue(Q,p->Rchild);
   }
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值