二叉树遍历的概念

二叉树的遍历是按某种规则对二叉树的每个节点均只被访问一次,根据根节点访问位置的不同分为三种:先序遍历(根左右)、中序遍历(左根右)、后序遍历(左右根)。
        由于树是通过不断递归生成的结构,在进行二叉树遍历时,也是一个递归遍历的过程。
下面用简单的图讲解三种遍历方式的区别

二叉树的先序遍历(根->左->右)

先序遍历的意思是首先访问根节点,首先访问根节点对应的左子树,再访问根节点对应的右子树。在访问左右子树时,此时左右子树作为新的根节点,继续递归访问该根节点的左右子树,如此反复,直到二叉树为空时返回遍历结果。
上图采用先序遍历访问这颗二叉树的详细过程为:
1.访问该二叉树的根节点,访问节点A,将A加入到序列中
2.访问节点A的左子树,即访问节点B,将B加入到序列中(此时B作为新的根节点,是一棵子树)
3.访问节点B的左子树,即访问节点D,将D加入到序列中
4.由于节点D没有左子树和右子树,因此节点D的子树遍历结束,但是对于B这个节点还没有遍历节点B的右子树,因此访问节点E,将E加入到序列中
5.由于节点E没有左子树和右子树,节点E的子树遍历结束,此时节点B作为根节点的左右节点遍历也结束
6.对节点B作为根节点的左右节点遍历结束意味着节点A的左子树遍历结束,此时开始遍历节点A的右子树,首先访问节点C,将C加入到序列中(此时C作为新的根节点,是一棵子树)
7.访问节点C的左子树,即访问节点F,将F加入到序列中
8.因为此时F无左右子树,即对节点F的子树遍历结束,但节点C还没有遍历右子树,因此访问G,至此对A的左右子树遍历完成,二叉树的先序遍历完成。先序遍历得到序列:ABDECFG
图示如下:

//二叉树先序遍历的递归实现(根-左-右)
void preorder(TreeNode* t){if(t == NULL) return ;visit(t) //输出t此时的节点值 类似于printf("%d",t->val) 即访问根节点preorder(t->left) //访问左子树preorder(t->right) //再访问右子树
}

二叉树的中序遍历(左->根->右)

中序遍历的意思是首先访问根节点的左子树,然后访问根节点,最后访问根节点对应的右子树,即遍历到到一个节点后,将其暂存,遍历完左子树后,再输出该节点的值,然后遍历右子树
上图采用中序遍历访问这颗二叉树的详细过程为:
1.访问二叉树的根节点,找到节点A
2.访问节点A对应的左子树,得到节点B(此时B作为新的根节点,是一棵子树)
3.访问节点B对应的左子树,得到节点D(此时D作为新的根节点,是一棵子树)
4.由于节点D没有左子树,将D加入到序列后,访问D的右子树,由于没有右子树,因此对D的子树遍历完成,即B的左子树遍历完成,回退到D的根节点B,将B加入到序列,然后遍历节点B的右子树
5.访问节点E,由于E没有左子树,即对E的左子树遍历完成,将E加入到序列中,继续访问E的右子树,因为E没有右子树,此时已经完成对节点B的中序遍历,即A的左子树遍历完毕
6.由于A的左子树遍历完毕,将A加入序列,开始遍历A的右子树
7.遍历A的右子树,首先得到节点C
8.对节点C形成的子树首先访问左子树,得到节点F,由于节点F没有左子树,因此将节点F加入到序列中,同时F也没有右子树,此时对C的左子树遍历完成,将C加入到序列
9.遍历节点C的右节点,得到节点G,对G这颗子树没有左子树,将G加入到序列,遍历G的右子树,无右子树,说明对C子树的的遍历完成,也表明对A的右子树遍历完成,整个过程结束
中序遍历得到的序列为:DBEAFCG
图示如下

//二叉树中序遍历的递归实现(左-根-右)
void inorder(TreeNode* t)
{if(t == NULL) return ;inorder(t->left);  //左节点visit(t);  //根节点inorder(t->right); //右节点
}

二叉树的后序遍历(左->右->根)

后序遍历的意思是首先访问根节点的左子树,然后访问根节点对应的根节点的右子树,再访问根节点,即访问到一个节点后,将其暂存,遍历完左右子树后,再输出该节点的值
上图采用后序遍历访问这颗二叉树的详细过程为:
1.访问二叉树的根节点,找到节点A
2.访问节点A对应的左子树,得到节点B(此时B作为新的根节点,是一棵子树)
3.访问节点B对应的左子树,得到节点D(此时B作为新的根节点,是一棵子树)
4.因为此时D没有左子树也没有右子树,将D加入序列中,代表对D的后序遍历已经结束,并回退到B(此时以B为根节点)
5.访问节点B对应的右子树,得到节点E(此时以E为根节点),此时E没有左子树也没有右子树,将E加入序列,对E子树的后序遍历结束,至此对B节点的左右子树遍历结束,将B加入序列,也表明此时对A的左子树全部遍历结束
6.遍历A的右子树,首先得到节点C(此时以C为根节点)
7.访问节点C对应的左子树,得到节点F(此时以F为根节点)
8.因为此时F没有左子树也没有右子树,将F加入序列中,代表对F的后序遍历已经结束,并回退到C(此时以C为根节点)
9.访问节点C对应的右子树,得到节点G(此时以G为根节点),此时G没有左子树也没有右子树,将G加入序列,对G子树的后序遍历结束,至此对C节点的左右子树遍历结束,将C加入序列,也表明此时对A的右子树全部遍历结束
10.对A的左右子树全部遍历结束,表明整个树的后序遍历结束
后序遍历得到的序列为:DEBFGCA
图示如下:

//二叉树后序遍历的递归实现(左-右-根)
void postorder(TreeNode* t){if(t == NULL) return ;postorder(t->left); //左节点postorder(t->right);  //右节点visit(t); //根节点
}

根据先序遍历和中序遍历得到后序遍历

给定先序遍历序列:ABDECFGH及中序遍历序列:DBEACGFH,求后续序列?
由于先序序列是由根—左—右不断递归得到的序列,而中序序列是由左—根—右递归得到的序列,根据两者特性的结合可以得到树的形状,因此可以得到后序遍历的结果
tip:(先序遍历确定一个子树的根节点,而中序遍历根据根节点将一颗子树再次分为左右子树)
1.因为先序遍历的特性可以得到访问的第一个节点一定是该树的根节点,再由中序遍历的特性,只有访问完根节点的左子树再访问根节点的特性再访问右子树,可以利用该特性得到此时根节点的左右子树情况,切分出根节点A的左子树DBE,根节点A的右子树CGFH,此时可以理解为(DBE)A(CGFH)

此时根节点为A
对A的左子树:先序遍历为BDE,中序遍历为DBE
对A的右子树:先序遍历为CFGH,中序遍历为CGFH

2.对A的左子树继续执行上述过程,可以确定B为A的左子树(先序遍历的第一个节点),同时直接根据中序遍历(左-根-右)可以确定D为B的左子树,E为B的右子树,对A的左子树遍历结束
3.对A的右子树递归执行上述过程,可以确定C为A的右子树(先序遍历的第一个节点),根据中序遍历可以确定GFH均为C的右子树,继续递归

此时根节点为C
对C的左子树:先序遍历为空,中序遍历为空
对C的右子树:先序遍历为FGH,中序遍历为GFH

4.对C的右子树递归执行上述过程,利用先序遍历可以确定F为C的右子树,再根据中序遍历确定G为F的左子树,H为F的右子树,遍历结束

5.根据还原的二叉树的图可以得出后序遍历的结果为DEBGHFCA

根据中序遍历和后序遍历得到前序遍历

给定中序遍历:BDAEGCF 后序遍历:DBGEFCA,求先序序列?
根据后序遍历确定根节点的位置(类似于前序遍历,只是遍历的顺序不一样),再根据中序遍历按根节点切分为左右子树,如此递归直至遍历结束
1.根据后序遍历的最后一个节点可以确定A为该树的根节点,再根据中序遍历的结果切分出A的左子树(BD)和A的右子树(EGCF),即(BD)A(EGCF)

此时根节点为A
对A的左子树:中序遍历为BD,后序遍历为DB
对A的右子树:中序遍历为EGCF,后序遍历为GEFC

2.对A的左子树继续递归执行上述过程,可以确定B为A的左子树(后序遍历的最后一个节点),根据中序遍历可以确定D是B的右子树,遍历结束
3.对A的右子树递归执行上述过程,确定C为A的右子树,再根据中序遍历且分出C的左子树(EG)以及C的右子树(F)

此时根节点为C(A的右子树)
对C的左子树:中序遍历为EG,后序遍历为GE
对C的右子树,中序遍历为F,后序遍历为F

4.继续对C的左子树做递归,可以确定E的C的左子树,且根据中序遍历确定G为E的右子树,遍历结束
因此可以根据中序遍历和后序遍历的结果得出该树

5.根据还原的二叉树的图可以得出先序遍历的结果为ABDCEGF

leetcode做题链接

二叉树的遍历
1.144.二叉树的前序遍历
2.94.二叉树的中序遍历
3.145.二叉树的后序遍历
重构二叉树
105.从前序和中序遍历序列构造二叉树
106.从中序和后续遍历序列构造二叉树

二叉树的前中后序遍历(考试常考)相关推荐

  1. 二叉树的前,中,后序遍历(思路分析) [Java][数据结构]

    二叉树的前,中,后序遍历(思路分析) 前序遍历: 先输出父节点, 再遍历左子树和右子树 中序遍历: 先遍历左子树, 再输出父节点,再遍历右子树 后序遍历: 先遍历左子树,再遍历右子树,最后输出父节点 ...

  2. Java二叉树的前中后序遍历

    Java二叉树的前中后序遍历 1.前序遍历 1.1前序遍历概念 1.2前序遍历习题 2.中序遍历 2.1中序遍历概念 2.2中序遍历习题 3.后续遍历 3.1后序遍历概念 3.2后序遍历习题 大家好, ...

  3. 数据结构之二叉树的前中后序遍历以及层序遍历

    学习目标:读完这篇博客搞定二叉树的前中后序以及层序遍历 首先:你应该明白什么是二叉树,下面这幅图就是一个完全二叉树 其实所谓的二叉树就是一个节点有小于等于二个分支的树,可以没有分支,可以有1条分支,可 ...

  4. 数据结构与算法(java):树-二叉树(二叉查找树(BST)、线索化二叉树、哈夫曼树、平衡二叉树【AVL】、二叉树的前中后序遍历)

    二叉树 1.定义 二叉树 就是度不超过2的树(每个结点最多只有两个子结点).如图 2.特殊二叉树 满二叉树 当二叉树的每一个层的结点树都达到最大值,则这个二叉树就是满二叉树. 完全二叉树 叶结点只能出 ...

  5. 二叉树的前中后序遍历之迭代法(非统一风格迭代方式)

    文章目录 前言 一.前序遍历(迭代法) 二.中序遍历(迭代法) 三.后序遍历(迭代法) 总结 前言 「递归的实现就是:每一次递归调用都会把函数的局部变量.参数值和返回地址等压入调用栈中」,然后递归返回 ...

  6. 【数据结构】二叉树的前中后序遍历

    二叉树的三种遍历 1. 创建一棵简单的二叉树 1.1 二叉树结构体实现 1.2 创造一个二叉树结点的函数 1.3 手动创造一棵二叉树 2.为什么要遍历? 3.最重要的知识:由二叉树引出的子问题分析 4 ...

  7. 二叉树的前中后序遍历之迭代法(统一风格迭代方式)

    一.前序遍历(迭代法)->右左中 前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子. 为什么要先加入 右孩子,再加入左孩子呢?因为这样出栈的时候 ...

  8. (必背)二叉树的前中后序遍历(利用栈)

    二叉树的前序遍历(利用栈) 1.首先将根节点压入栈 2.栈中的首元素出栈,然后先将其右节点压入栈中,再将栈中的左节点压入栈中(如果左右节点分别存在的话) 3.重复步骤2直到栈为空 class Solu ...

  9. 二叉树的前中后序遍历(栈)(C++)

    二叉树的遍历是很基础的东西,用递归是很简洁明了的写法,但是栈的写法也可以了解一下 #include<vector> #include<stack> struct TreeNod ...

最新文章

  1. 医疗影像处理:去除医疗影像中背景的影响2D/3D【numpy-code】| CSDN博文精选
  2. 知道这20个正则表达式,能让你少写1,000行代码
  3. Windows 下OpenSSL 安装详解 +图解
  4. 解决在Win2008下IIS7不显验证码的问题
  5. 1-26HashSet简介
  6. 神经网络与深度学习——TensorFlow2.0实战(笔记)(四)(python文件)
  7. 华为路由器上有没有mac表_MAC地址表、ARP缓存表、路由表及交换机、路由器基本原理...
  8. linux指令能回滚么,如何在Ubuntu上撤消或回滚“ apt-get upgrade”命令?
  9. ubuntu安装msql5.7
  10. Heroku应用程序在尝试运行时不断崩溃怎么解决
  11. iphone引用自定义字体 html,在网页上使用苹果字体
  12. Wsus更新失败错误代码:0x80244022故障排除
  13. 视频、图像原理 设配选择 图像出入门概念理解
  14. 手机无线如何共享给台式计算机,教你用手机做热点分享wifi给台式电脑用,不是用数据网络哦...
  15. Redux-前端开发者的福音
  16. 蓝奏云链接打不开的解决办法
  17. Unity 制作font字体
  18. PHP判断来访是搜索引擎蜘蛛还是普通用户的代码小结
  19. 公司网站制作需要多少钱?先了解这三个要点!
  20. IBM启动2014三大战略方向

热门文章

  1. 太尴尬了,网关配置错误一直404
  2. Matlab画图函数
  3. 如何将电影台词拼接到一张图上?这4种台词拼接方法亲测好用
  4. python实验指导书答案_《python编程基础》实验指导书.doc
  5. python入门——全局函数思维导图
  6. redis--Linux环境下安装步骤
  7. 沈孝钧计算机算法基础答案,计算机算法基础
  8. 用计算机研究心理,浅析计算机在心理学研究中的应用
  9. 【Bluetooth开发】蓝牙开发入门
  10. 海康威视web无插件开发包webVideoCtrl.js+vue做网页开发