二叉树的遍历

对于二叉树的操作,大家可能会想到二叉树的三种遍历:先序遍历、中序遍历以及后序遍历。下面我们来讲述二叉树的这三种遍历,大约10-15分钟左右读完,希望大家找只笔和纸,手写一下!!!

 

一、先序遍历

1.先序遍历思想

(1)若二叉树为空,则为空操作,返回空

(2)访问根结点

(3)先序遍历左子树

(4)先序遍历右子树

  • 先序遍历的递归算法
 void PreOrderTraverse(BiTree BT)
   {
     if(BT)
     {
        printf("%c",BT->data);              //访问根结点
        PreOrderTraverse(BT->lchild);       //前序遍历左子树
        PreOrderTraverse(BT->rchild);       //前序遍历右子树
     }
   }
  • 使用栈保存每个节点右子树的二叉树先序遍历的非递归算法

(1)当树为空时,将指针p指向根结点,p为当前结点指针

(2)先访问当前结点p,并将p压入栈中

(3)令p指向左孩子

(4)重复执行步骤(2)和(3),直到p为空为止

(5)从栈中弹出栈顶元素,将p指向此元素的右孩子

(6)重复执行步骤(2)~(5),直到p为空并且栈S也为空 ,最后结束遍历

void PreOrderNoRec(BiTree BT)
      {
        stack S;
        BiTree p=BT->root;
        while((NULL!=p)||!StackEmpty(S))
        {
          if(NULL!=p)
          {
            printf("%c",p->data);
            Push(S,p);
            p=p->lchild;
          }
          else
          {
            p=Top(S);
            Pop(S);
            p=p->rchild;
          }
        }
      }

 

二、中序遍历

 (1)若二叉树为空,则为空操作,返回空。
 (2)中序遍历左子树。
 (3)访问根结点。
 (4)中序遍历右子树。

  • 中序遍历的递归算法
 void InOrderTraverse(BiTree BT)
    {
      if(BT)
      {
         InOrderTraverse(BT->lchild);        //中序遍历左子树
         printf("%c",BT->data);              //访问根结点
         InOrderTraverse(BT->rchild);        //中序遍历右子树
      }
    }
  • 使用栈存储中序遍历的非递归算法

  (1)当树为空时,将指针p指向根结点,p为当前结点指针。
  (2)将p压入栈S中,并令p指向其左孩子。
  (3)重复执行步骤(2),直到p为空。
  (4)从栈S中弹出栈顶元素,将p指向此元素。
 (5)访问当前结点p,并将p指向其右孩子。
 (6)重复执行步骤(2)~(5),直到p为空并且栈S也为空。
 (7)遍历结束。

void IneOrderNoRec(BiTree BT)
     {
       stack S;
       BiTree p=BT->root;
       while((NULL!=p)||!StackEmpty(S))
       {
         if(NULL!=p)
         {
           Push(S,p);
           p=p->lchild;
         }
         else
         {
           p=Top(S);
           Pop(S);
           printf("%c",p->data);
           p=p->rchild;
         }
       }
     }

 

三、后序遍历

(1)若二叉树为空,则为空操作,返回空。

(2)后序遍历左子树。
(3)后序遍历右子树。

(4)访问根结点。

  • 后序遍历的递归算法
void PostOrderTraverse(BiTree BT)
     {
       if(BT)
       {
          PostOrderTraverse(BT->lchild);        //后序遍历左子树
          PostOrderTraverse(BT->rchild);        //后序遍历右子树
          printf("%c",BT->data);                //访问根结点
       }
     }
  • 使用栈来存储后序遍历的非递归算法

首先扫描根结点的所有左结点并入栈,然后出栈一个结点,扫描该结点的右结点并入栈,再扫描该右结点的所有左结点并入栈,当一个结点的左、右子树均被访问后再访问该结点。因为在递归算法中,左子树和右子树都进行了返回,因此为了区分这两种情况,还需要设置一个标识栈tag,当tag的栈顶元素为0时表示从左子树返回,为1表示从右子树返回。

(1)当树为空时,将指针p指向根结点,p为当前结点指针。
(2)将p压入栈S中,0压入栈tag中,并令p指向其左孩子。
(3)重复执行步骤(2),直到p为空。
(4)如果tag栈中的栈顶元素为1,跳至步骤(6)。
(5)如果tag栈中的栈顶元素为0,跳至步骤(7)。
(6)将栈S的栈顶元素弹出,并访问此结点,跳至步骤(8)。
(7)将p指向栈S的栈顶元素的右孩子。
(8)重复执行步骤(2)~(7),直到p为空并且栈S也为空。
(9)遍历结束。

void PostOrderNoRec(BiTree BT)
       {
         stack S;
         stack tag;
         BiTree p=BT->root;
         while((NULL!=p)||!StackEmpty(S))
         {
           while(NULL!=p)
           {
             Push(S,p);
             Push(tag,0);
             p=p->lchild;
           }
           if(!StackEmpty(S))
           {
             if(Pop(tag)==1)
             {
               p=Top(S);
               Pop(S);
               printf("%c",p->data);
               Pop(tag);    //栈tag要与栈S同步
             }
             else
             {
               p=Top(S);
               if(!StackEmpty(S))
               {
                 p=p->rchild;
                 Pop(tag);
                 Push(tag,1);
               }
             }
           }
         }
       }

 

以上就是二叉树对的遍历部分思想,希望可以对大家对二叉树遍历有所帮助


   

posted @ 2018-08-01 17:36  国孩  阅读(287)  评论(0编辑  收藏  举报