当前位置: 首页 > article >正文

【C++二叉树】二叉树的前序遍历、中序遍历、后序遍历递归与非递归实现

1.二叉树的前序遍历

144. 二叉树的前序遍历 - 力扣(LeetCode)
 

前序遍历方式:根-左子树-右子树。

递归实现:

要传一个子函数来实先递归,原因是原函数返回值为vector,在原函数迭代,返回值就难处理了。

非递归(迭代)实现:

递归实现非常简单,非递归呢?

要用迭代实现,也就是循环:

还是按照根-左子树-右子树的遍历方式遍历。

遍历:先访问1、3、4再访问4的右子树再退回去访问3的右子树和1的右子树。

这时,我们可以把树分为左路节点和左路节点的右子树。

也就是先访问左路节点再访问左路节点的右子树,右子树也同样分为左路节点和左路节点的右子树。

这时,就要使用栈来解决:

  1. 把左路节点入栈,入栈的同时访问节点(遍历根),当左路节点为空时停止入栈,同时也证明左子树已经访问结束。
  2. 这时再访问左路节点的右子树。取栈顶数据(栈顶数据就是左路节点)的右子树,再把栈顶数据弹出。
  3. 右子树同样分为左路节点和左路节点的右子树,同样按照此方法迭代循环。
  4. 直到最后一个节点访问结束,此时,节点为空,栈为空。

自己根据代码,画一下图模拟迭代过程就容易理解了。

2.二叉树的中序遍历

94. 二叉树的中序遍历 - 力扣(LeetCode)

中序遍历方式:左子树-根-右子树。

递归实现:

非递归(迭代)实现:

中序遍历的非递归和前序遍历的非递归思路类似。

  1. 都是按照把树分为左路节点和左路节点的右子树的思路来实现的,只不过访问节点(根)的时机不同。
  2. 前序遍历是先访问根再访问左子树右子树,所以在左路节点入栈的时候,就访问节点(根),而中序遍历是先访问左子树再访问根再访问右子树
  3. 所以中序遍历是在左路节点入栈完以后,再访问节点(根)。

3.二叉树的后序遍历

145. 二叉树的后序遍历 - 力扣(LeetCode)

后序遍历方式:左子树-右子树-根

递归实现:

非递归迭代实现:

后序遍历方式:左子树-右子树-根

后序遍历的非递归与前序和中序的非递归整体思路类似。

唯一不同的就是访问节点的时机不同。

什么时候访问节点(根)呢?

  1. 从栈中取出左路节点时,节点的左子树已经访问完了(理解理解)。
  2. 当左路节点的右子树访问完才可以访问根。
  3. 如果左路节点的右子树为空,则代表右子树访问完,可以访问节点(根)了。
  4. 如果右子树不为空,则要先访问左路节点的右子树。

非递归迭代实现:

但是此时会发现超出了内存限制,说明代码有问题,内存限制问题一般就是死循环了。

按照上面的代码,会发现,节点3和节点5之间会一直死循环,

  1. 3的右子树不为空,把5入栈,5的右子树为空,把栈中5弹出来,下次循环又取了栈顶数据3,3的右子树不为空,把5入栈......
  2. 第二次访问节点3的时候,就应该直接访问节点(根)了,但他的右子树不为空,又访问了右子树,他不知道右子树已经访问过了,就会不断的进入3的右子树访问就死循环了。

所以,关键问题就说我们要想一个办法区分他的右子树到底访问过了没有,如果访问过了,则可以访问该左路节点(根)了,如果没有访问,则先访问他的右子树。

此时,可以使用双指针来解决,我们定义一个指针lastNode表示当前节点的上一个节点。

访问节点3的时候,lastNode为右子树的根(节点5),代表右子树已经访问完了,则就可以访问该节点了。

非递归(迭代)实现:



4.总结:

  • 前序遍历、中序遍历、后序遍历的递归实现很简单,但是非递归迭代实现就有稍微有点难理解了。
  • 用了同一种思路,把树分为左路节点和左路节点的右子树,针对这三种遍历方式都适用。
  • 从根本上就是用循环模拟递归的过程。
  • 后序遍历相对前序和中序又稍微复杂,要考虑好访问节点的条件,避免死循环。
  • 多画图模拟迭代的过程更容易理解。


http://www.kler.cn/a/314793.html

相关文章:

  • Database Advantages (数据库系统的优点)
  • androidstudio下载gradle慢
  • AI大模型开发架构设计(18)——基于大模型构建企业知识库案例实战
  • C语言 | Leetcode C语言题解之第557题反转字符串中的单词III
  • ubuntu20.04 解决Pytorch默认安装CPU版本的问题
  • OpenGL ES 共享上下文实现多线程渲染
  • Kotlin 极简小抄 P3(函数、函数赋值给变量)
  • LeetCode 第416场周赛个人题解
  • springbootweb集成swagger
  • 王道考研视频——操作系统笔记
  • 海外服务器哪个速度最快且性能稳定
  • GRE隧道在实际部署中的优化、局限性与弊端
  • 排序篇(七大基于比较的排序算法)
  • 华为全联接大会HC2024 观会感
  • QMT获取可转债行情数据方法介绍!支持QMT量化软件的券商平台?
  • Oracle(140)如何创建和管理数据库角色?
  • Android14 蓝牙启动流程
  • C++编程语言:基础设施:命名空间(Bjarne Stroustrup)
  • 基于微信小程序的购物系统+php(lw+演示+源码+运行)
  • App端测——稳定性测试
  • 笔记整理—内核!启动!—linux应用编程、网络编程部分(1)API概述与文件I/O
  • 互联网技术的持续演进:从现在到未来
  • 开放的数据时代:Web3和个人隐私的未来
  • 自动化流程机器人(RPA)
  • 计算机图形学 中心画圆算法 原理及matlab代码实现
  • 『功能项目』QFrameWorkBug拖拽功能【66】