二叉树遍历算法总结

article/2025/10/8 17:41:14

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);      //访问结点ptop=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);      //访问结点pp=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);      //访问结点pp=NULL;}}while((top>0));}

B 线索化二叉树:

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

                 

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

复制代码

      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;elsep->ltag=1;if(p->rchild)p->rtag=0;elsep->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/wp5719/p/5523973.html)


http://chatgpt.dhexx.cn/article/hsojmDvr.shtml

相关文章

二叉树的遍历算法

遍历是对树的一种最基本的运算,所谓遍历二叉树,就是按一定的规则和顺序走遍二叉树的所有节点,使每一个节点都被访问一次,而且只被访问一次。由于二叉树是非线性结构,因此,树的遍历实质上是将二叉树的各个节…

【算法】二叉树遍历算法总结:前序中序后序遍历

前言 二叉树遍历是非常经典的算法题,也是二叉树的一道基础算法题。 但是在平常的笔试面试中,其出现的频率其实并不是特别的高,我推测是这种题目相对来说比较基础,算是一个基础知识点。 比如剑指offer中出现的后序遍历题目&…

二叉树遍历算法的应用

目录 一、二叉树遍历算法的应用——二叉树的创建 二、二叉树遍历算法的应用——复制二叉树 三、二叉树遍历算法的应用——计算二叉树的深度 四、二叉树遍历算法的应用——计算二叉树节点总数 五、二叉树遍历算法的应用——计算二叉树叶子节点数 一、二叉树遍历算法的应用—…

一文弄懂二叉树的三种遍历方式

关注公众号【高性能架构探索】,后台回复【pdf】,免费获取计算机必备经典书籍 俗话说:学如逆水行舟,不进则退;心似平原走马,易放难收。这句话对程序员而言,体会更深。这行已经越来越卷了,时刻准备着,&#x…

二叉树遍历算法

目录 先序遍历 中序遍历 后序遍历 层序遍历 938. 二叉搜索树的范围和 110. 平衡二叉树 114. 二叉树展开为链表 117. 填充每个节点的下一个右侧节点指针 II 116. 填充每个节点的下一个右侧节点指针 1,三种遍历都是先把二叉树的最左结点循环入栈(DFS迭代)&am…

二叉树的四种遍历算法(结构体数组)

一、二叉树的定义 以字符串的形式定义一棵二叉树的先序序列,若字符是‘#’,表示该二叉树是空树,否则该字符是相应结点的数据元素。 例:ABDG##HI####CE#J##F## 对应的二叉树: 思路讲解: 想要遍历二叉树&am…

二叉树的四种遍历方式

概要 树本身是一种简单化的图 ; DFS对应前中后序遍历,BFS对应层序遍历 二叉树结构 struct treenode {int val;treenode *left;treenode *right;treenode() : val(0), left(nullptr), right(nullptr) {}treenode(int x) : val(x), left(nullptr), right(n…

针对Linux学习,值得阅读的五本书籍,不看可能错失机会

今天为了总结一些可以帮助各位在学习过程中提供帮助的一些书籍。 一.鸟叔的私房菜: 本书是知名度颇高的Linux入门书《鸟哥的Linux私房菜基础学习篇》的新版,而详细地介绍了Linux操作系统。全书分为五部分;第一部分部分着重说明计算机的基础知识、Linux的学习方法&a…

从零开始学习Linux(一)关闭虚拟机系统

关闭系统,需要输入如下命令 poweroff然而,你只能得到如下反馈 -bash: poweroff:command not found此项错误是因为poweroff命令是一个系统管理命令。执行此项命令需要高级使用者特权。 因此,为了关闭系统,我们首先需要切换到root…

个人随笔/小白应该如何学习Linux,我的一些心得分享.

大家好,今天给大家分享一下0基础的人如何入门Linux,此文来源:我在上班的路上看到一篇文章,也是写的0基础的人如何学习Linux的文章。当时我在想,我写博文一年多,都是相关Linux及Python等技术的文章&#xff…

Linux学习路线

 关于 Linux Linux 因其开源,免费,可裁剪,被应用到很多领域,尤其是嵌入式设备上。 Android 系统内核也是基于 Linux 的。 另外还有各种服务器和工作站也是用的 Linux。 什么是嵌入式设备?…

为什么要学习 Linux ????

目前企业中大量的使用Linux作为服务器,在以后你们就业后,会发现web服务器Tomcat ,jobss这一类都是搭建在linux上面的,后面我们需要学习的数据库mysql , oracle ,db2, 或者greenplum这一类的,在企…

Linux 学习路线图

1.应用场景 更加高效地学习并达到运用Linux. 2.学习/操作 linux运维学习需要分为四个阶段:初级入门、中级进阶、高级提升、资深方向细化。 第一阶段:初级入门 初级阶段需要把linux学习路线搞清楚,任何学习都是循序渐进的,所以学…

从零入门机器学习之Linux系统详解

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,科大讯飞比赛第三名,CCF比赛第四名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

为什么要学习Linux?

对于一些偶然接触到Linux的人来说,好奇是对于这个陌生名词的的第一印象。也许这个名字经常出现在你所使用的教科书上,或者是一些技术性的文章上,你却不知其意,此时这个名字再次出现,你就更是好奇了,Linux到…

Linux学习总结

课程:Linux操作系统与应用 参考书:Linux从入门到精通、unix环境高级编程 学习linux之前必须要做好心理准备: 第一,要明白学好linux不是一件一蹴而就的事,一定要能坚持使用它,特别是在使用初期&#xff0c…

你知道如何学习Linux吗?

说起Linux,业内人士或者经常玩电脑,对计算机比较精通的应该是比较熟悉的,Linux是一个开源的操作系统,由于其安全性高,完全免费,高效性,稳定等优点,越来越受大众的欢迎,就…

学习linux的感受

学习前要 1.安装虚拟机或者自己买个云服务器 下载centOs然后将镜像装入系统 2.装入之后在自己的电脑下载Xshell和Xbox 3在自己windows系统下运行cmd拼一下自己的虚拟机或服务器测试两个机子网络是否相通,如果相通即可用Xshell进行远程登陆 成果: 今天学了vim与vi&…

初学者如何系统性地学习Linux?

作为一个大一的同学,可以采取下面的步骤进行系统的学习Linux。 1、选择一个发行版:对于初学者,推荐使用Ubuntu或者Linux Mint。Ubuntu适合新手,使用广泛,社区活跃,遇到问题容易找到解决方案。虽然你觉得Ub…

如何学习Linux

热热热 一、Linux大致要学习那些内容 1、Linux下的基本操作命令 2、Linux的各种配置 环境变量、网络的配置、服务的配置----常规而重要 3、Linux下搭建各种开发环境 例如: Javaee、大数据、Python等 4、能够写一些基本的shell脚本,对Linux系统进…