zoukankan      html  css  js  c++  java
  • 二叉树的遍历

    对于二叉树的操作,大家可能会想到二叉树的三种遍历:先序遍历、中序遍历以及后序遍历。下面我们来讲述二叉树的这三种遍历,大约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);
                   }
                 }
               }
             }
           }

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


       

  • 相关阅读:
    ECharts中悬浮图标tooltie多行显示已解决
    Linux中的$符号的三种常见用法
    Shell逐行读取文件的4种方法
    rename
    nodejs安装
    “ArcGIS Desktop遇到严重的应用程序错误,无法继续”的解决方案
    跟我一起学Redis之Redis持久化必知必会
    微服务很香--麻辣味,但要慢慢消化
    跟我一起学Redis之Redis事务简单了解一下
    跟我一起学.NetCore之EF Core 实战入门,一看就会
  • 原文地址:https://www.cnblogs.com/guohai-stronger/p/9401456.html
Copyright © 2011-2022 走看看