二叉树遍历算法总结

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??二叉树遍历算法总结

? ??

? ?本文依据《数据结构与算法》(C语言版)(第三版) 整理。

? ?A. ?二叉树的遍历

? ? ? 1.前序遍历二叉树:

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

? ? ? ? (2)訪问根结点。
? ? ? ? (3)前序遍历左子树。

? ? ? ? (4)前序遍历右子树。

? ? ??a.二叉树前序遍历的递归算法:

   void PreOrderTraverse(BiTree BT)
   {
     if(BT)
     {
        printf("%c",BT->data);              //訪问根结点
        PreOrderTraverse(BT->lchild);       //前序遍历左子树
        PreOrderTraverse(BT->rchild);       //前序遍历右子树
     }
   }

? ??b.使用栈存储每一个结点右子树的二叉树前序遍历的非递归算法:

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

? ? ? (2)先訪问当前结点p。并将p压入栈S中。

? ? ? (3)令p指向其左孩子。
? ? ? (4)反复运行步骤(2)、(3)。直到p为空为止。
? ? ? (5)从栈S中弹出栈顶元素。将p指向此元素的右孩子。
? ? ? (6)反复运行步骤(2)~(5),直到p为空而且栈S也为空。
? ? ? (7)遍历结束。

? ? ??使用栈的前序遍历的非递归算法:

      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;
          }
        }
      }

? ??c.使用二叉链表存储的二叉树前序遍历非递归算法:

    void PreOrder(pBinTreeNode pbnode)
    {
      pBinTreeNode stack[100];
      pBinTreeNode p;
      int top;
      top=0;
      p=pbnode;
      do
      {
        while(p!=NULL)
        {
          printf("%d\n",p->data);      //訪问结点p
          top=top+1;
          stack[top]=p;
          p=p->llink;                  //继续搜索结点p的左子树
        }
        if(top!=0)
        {
          p=stack[top];
          top=top-1;
          p=p->rlink;                  //继续搜索结点p的右子树
        }
      }while((top!=0)||(p!=NULL));
    }

? ? 2.中序遍历二叉树:

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

? ? ? (2)中序遍历左子树。
? ? ? (3)訪问根结点。
? ? ? (4)中序遍历右子树。

? ? ? a.二叉树中序遍历的递归算法:

    void InOrderTraverse(BiTree BT)
    {
      if(BT)
      {
         InOrderTraverse(BT->lchild);        //中序遍历左子树
         printf("%c",BT->data);              //訪问根结点
         InOrderTraverse(BT->rchild);        //中序遍历右子树
      }
    }

? ? ??b.使用栈存储的二叉树中序遍历的非递归算法:

? ? ? ?(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;
         }
       }
     }

? ? ? ?c.使用二叉链表存储的二叉树中序遍历非递归算法:

    void InOrder(pBinTreeNode pbnode)
    {
         pBinTreeNode stack[100];
         pBinTreeNode p;
         int top;
         top=0;
         p=pbnode;
         do
         {
           while(p!=NULL)
           {
             top=top+1;
             stack[top]=p;                //结点p进栈
             p=p->llink;                  //继续搜索结点p的左子树
           }
           if(top!=0)
           {
             p=stack[top];                //结点p出栈
             top=top-1;
             printf("%d\n",p->data);      //訪问结点p
             p=p->rlink;                  //继续搜索结点p的右子树
           }
         }while((top!=0)||(p!=NULL));
    }

? ? ??

? ??3.后序遍历二叉树:

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

? ? ? (2)后序遍历左子树。
? ? ? (3)后序遍历右子树。
? ? ? (4)訪问根结点。

? ? ??a.二叉树后序遍历的递归算法:

     void PostOrderTraverse(BiTree BT)
     {
       if(BT)
       {
          PostOrderTraverse(BT->lchild);        //后序遍历左子树
          PostOrderTraverse(BT->rchild);        //后序遍历右子树
          printf("%c",BT->data);                //訪问根结点
       }
     }

? ? ??b.使用栈存储的二叉树后序遍历的非递归算法:

? ? ? 算法思想:首先扫描根结点的全部左结点并入栈,然后出栈一个结点,扫描该结点的右结点并入栈,再扫描该右结点的全部左结点并入栈,当一个结点的左、右子树均被訪问后再訪问该结点。由于在递归算法中。左子树和右子树都进行了返回,因此为了区分这两种情况。还须要设置一个标识栈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);
               }
             }
           }
         }
       }

? ? ?c.使用二叉链表存储的二叉树后序遍历非递归算法:

     void PosOrder(pBinTreeNode pbnode)
     {
          pBinTreeNode stack[100];       //结点的指针栈
          int count[100];                //记录结点进栈次数的数组
          pBinTreeNode p;
          int top;
          top=0;
          p=pbnode;
          do
          {
            while(p!=NULL)
            {
              top=top+1;
              stack[top]=p;                //结点p首次进栈
              count[top]=0;
              p=p->llink;                  //继续搜索结点p的左子树
            }
            p=stack[top];                  //结点p出栈
            top=top-1;
            if(count[top+1]==0)
            {
              top=top+1;
              stack[top]=p;                //结点p首次进栈
              count[top]=1;
              p=p->rlink;                  //继续搜索结点p的右子树
            }
            else
            {
              printf("%d\n",p->data);      //訪问结点p
              p=NULL;
            }
          }while((top>0));
     }

? ? ?B 线索化二叉树:

? ? ? ?线索化二叉树的结点结构图:

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" />

? ? ? ?线索化二叉树的结点类型说明:

      typedef struct node
      {
        DataType data;
        struct node *lchild, *rchild;       //左、右孩子指针
        int ltag, rtag;                     //左、右线索
      }TBinTNode;         //结点类型
      typedef TBinTNode *TBinTree;

? ? ? ?在线索化二叉树中。一个结点是叶子结点的充分必要条件是其左、右标志均为1.

? ? ?中序线索化二叉树及其相应的线索链表例如以下图:

? ? ? ? ? ? ? ? ? ? ? ?

? ? ? (1)中序线索化二叉树的算法:

       void InOrderThreading(TBinTree p)
      {
        if(p)
        {
          InOrderThreading(p->lchild);   //左子树线索化
          if(p->lchild)
            p->ltag=0;
          else
            p->ltag=1;
          if(p->rchild)
            p->rtag=0;
          else
            p->rtag=1;
          if(*(pre))      //若*p的前驱*pre存在
          {
            if(pre->rtag==1)
              pre->rchild=p;
            if(p->ltag==1)
              p->lchild=pre;
          }
          pre=p;                         //另pre是下一訪问结点的中序前驱
          InOrderThreading(p->rchild);   //右子树线索化
        }
      }

? ? ? ?

? ??(2)在中序线索化二叉树下,结点p的后继结点有下面两种情况:

? ? ? ①结点p的右子树为空。那么p的右孩子指针域为右线索,直接指向结点p的后继结点。
? ? ? ②结点p的右子树不为空。那么依据中序遍历算法。p的后继必是其右子树中第1个遍历到的结点。

? ? ??

? ? ?中序线索化二叉树求后继结点的算法:

    TBinTNode *InOrderSuc(BiThrTree p)
    {
       TBinTNode *q;
       if(p->rtag==1)   //第①情况
         return p->rchild;
       else            //第②情况
       {
         q=p->rchild;
         while(q->ltag==0)
           q=q->lchild;
         return q;
       }
    }

? ? ? 中序线索化二叉树求前驱结点的算法:

    TBinTNode *InOrderPre(BiThrTree p)
    {
       TBinTNode *q;
       if(p->ltag==1)
         return p->lchild;
       else
       {
         q=p->lchild;         //从*p的左孩子開始查找
         while(q->rtag==0)
           q=q->rchild;
         return q;
       }
    }

? ? ?(3)遍历中序线索化二叉树的算法

    void TraversInOrderThrTree(BiThrTree p)
    {
      if(p)
      {
        while(p->ltag==0)
          p=p->lchild;
        while(p)
        {
          printf("%c",p->data);
          p=InOrderSuc(p);
        }
      }
    }

原文地址:https://www.cnblogs.com/zhchoutai/p/8452087.html

时间: 2024-10-11 12:22:07

二叉树遍历算法总结的相关文章

morris算法-----高级二叉树遍历算法

在遍历儿叉树时,常常使用的是递归遍历,或者是借助于栈来迭代,在遍历过程中,每个节点仅访问一次,所以这样遍历的时间复杂度为O(n),空间复杂度为O(n),并且递归的算法易于理解和实现.在遍历过程中,递归遍历过程的空间复杂度却是O(n),就算是转换为使用栈空间迭代时间,还是没有改变算法对额外空间的需求,在学习数据结构课程时,还学习了线索二叉树,在线索二叉树中,使用线索来保存节点的前驱和后继的信息,而这些线索是利用了叶节点的空指针域来保存,所以知道了树种每个节点的前驱和后继的位置(指针)可以有效降低遍

Binary Tree Traversal Algorithms (二叉树遍历算法)

本文共列出了11个常见的二叉树遍历算法.二叉树的遍历主要有深度优先遍历和广度优先遍历.深度优先遍历包含前序遍历.中序遍历和后序遍历. 值得一提的是, 其中的 Morris 算法 可以线性时间不需要额外空间(用户栈或系统栈空间)实现二叉树的前序遍历.中序遍历和后序遍历.关于Morris算法, 可参考 http://www.cnblogs.com/AnnieKim/archive/2013/06/15/morristraversal.html 算法清单: A1. A2. A3, 分别是中序遍历的递归

二叉树遍历算法总结(递归与非递归)

一:前言 二叉树的遍历方法分四种:前序,中序,后序以及层次遍历. 其中,前中后遍历方法的实现分递归和非递归,非递归遍历的实现需要借助于栈. 实际上,递归的调用就是一种栈的实现,所以,非递归遍历就需要人工借助栈结构来实现. 而层次遍历需要借助队列. 二:前中后序遍历 递归遍历: 递归遍历的思想和方法很简单,通过调整输出语句来实现前,中,后三种遍历. 代码如下: 1 void show(BiTree T) 2 { 3 if(T) 4 { 5 printf("%c ",T->data)

python实现二叉树遍历算法

说起二叉树的遍历,大学里讲的是递归算法,大多数人首先想到也是递归算法.但作为一个有理想有追求的程序员.也应该学学非递归算法实现二叉树遍历.二叉树的非递归算法需要用到辅助栈,算法着实巧妙,令人脑洞大开. 以下直入主题: 定义一颗二叉树,请看官自行想象其形状, class BinNode( ): def __init__( self, val ): self.lchild = None self.rchild = None self.value = val binNode1 = BinNode( 1

二叉树遍历算法——包含递归前、中、后序和层次,非递归前、中、后序和层次遍历共八种

首先,要感谢网上的参考资料. http://mengliao.blog.51cto.com/876134/1178079(作者:BlackAlpha) http://blog.csdn.net/fzh1900/article/details/14056735(作者:_云淡风轻) http://blog.csdn.net/stpeace/article/details/8138458(作者:stpeace) 二叉树是使用的比较广泛的一种数据结构,这里我写了二叉树的相关操作,包括初始化.新建.以及遍

二叉树遍历算法

二叉树是树(Tree)这一数据结构中非常重要的子类,其中每一个节点最多存在两个子节点,在代码中表示就是,除了本身的 Data 值,还会带有 Left 和 Right 子节点.如下图所示,用形如图中的结构构成了整棵树. 任何一种数据结构,都会存在遍历的顺序问题,比如链表,堆栈等等:二叉树这种数据结构也有遍历的顺序,由于其非线性的结构特征,遍历时的顺序有这三种,前序(pre-order),中序(in-order),后序(post-order).下面依次介绍一下: 1 前序(pre-order)遍历

数据结构(二十一)二叉树遍历算法的应用与二叉树的建立

一.顺序存储结构对树这种一对多的关系结构实现起来是比较困难的.但是二叉树是一种特殊的树,由于它的特殊性,使得用顺序存储结构也可以实现. 二.二叉树的顺序存储结构就是用一维数组存储二叉树中的结点,并且结点的存储位置,也就是数组的下标要能体现结点之间的逻辑关系,比如双亲与孩子的关系,左右兄弟的关系等. 三.完全二叉树可以将相应下标的结点存到数组的相应下标的位置上,对于一般的二叉树来说,完全可以将其按完全二叉树编号,只不过,把不存在的结点设置为"null"而已.这显然是对存储空间的浪费,所以

java数据结构之二叉树遍历的非递归实现

算法概述递归算法简洁明了.可读性好,但与非递归算法相比要消耗更多的时间和存储空间.为提高效率,我们可采用一种非递归的二叉树遍历算法.非递归的实现要借助栈来实现,因为堆栈的先进后出的结构和递归很相似.对于中序遍历来说,非递归的算法比递归算法的效率要高的多.其中序遍历算法的实现的过程如下:(1).初始化栈,根结点进栈:(2).若栈非空,则栈顶结点的左孩子结点相继进栈,直到null(到叶子结点时)退栈:访问栈顶结点(执行visit操作)并使栈顶结点的右孩子结点进栈成为栈顶结点.(3).重复执行(2),

数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树

[本文谢绝转载,原文来自http://990487026.blog.51cto.com] 树 数据结构与算法 3:二叉树,遍历,创建,释放,拷贝,求高度,面试,线索树 二叉树的创建,关系建立 二叉树的创建,关系建立2 三叉链表法 双亲链表: 二叉树的遍历 遍历的分析PPT 计算二叉树中叶子节点的数目:使用全局变量计数器 计算二叉树中叶子节点的数目:不使用全局变量计数器 无论是先序遍历,中序遍历,后序遍历,求叶子的数字都不变;因为本质都是一样的,任何一个节点都会遍历3趟 求二叉树的高度 二叉树的拷