此时我们在二叉树:一入递归深似海,从此offer是路人中用递归的方式,实现了二叉树前中后序的遍历。

在二叉树:听说递归能做的,栈也能做!中用栈实现了二叉树前后中序的迭代遍历(非递归)。

之后我们发现「迭代法实现的先中后序,其实风格也不是那么统一,除了先序和后序,有关联,中序完全就是另一个风格了,一会用栈遍历,一会又用指针来遍历。」

实践过的同学,也会发现使用迭代法实现先中后序遍历,很难写出统一的代码,不像是递归法,实现了其中的一种遍历方式,其他两种只要稍稍改一下节点顺序就可以了。

其实「针对三种遍历方式,使用迭代法是可以写出统一风格的代码!」

「重头戏来了,接下来介绍一下统一写法。」

我们以中序遍历为例,在二叉树:听说递归能做的,栈也能做!中提到说使用栈的话,「无法同时解决访问节点(遍历节点)和处理节点(将元素放进结果集)不一致的情况」

「那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。」

如何标记呢,「就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记。」 这种方法也可以叫做标记法。

迭代法中序遍历

中序遍历代码如下:(详细注释)

class Solution {
public:vector<int> inorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if (root != NULL) st.push(root);while (!st.empty()) {TreeNode* node = st.top();if (node != NULL) {st.pop(); // 将该节点弹出,避免重复操作,下面再将右中左节点添加到栈中if (node->right) st.push(node->right);  // 添加右节点(空节点不入栈)st.push(node);                          // 添加中节点st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。if (node->left) st.push(node->left);    // 添加左节点(空节点不入栈)} else { // 只有遇到空节点的时候,才将下一个节点放进结果集st.pop();           // 将空节点弹出node = st.top();    // 重新取出栈中元素st.pop();result.push_back(node->val); // 加入到结果集}}return result;}
};

看代码有点抽象我们来看一下动画(中序遍历):

中序遍历迭代(统一写法)

动画中,result数组就是最终结果集。

可以看出我们将访问的节点直接加入到栈中,但如果是处理的节点则后面放入一个空节点, 这样只有空节点弹出的时候,才将下一个节点放进结果集。

此时我们再来看前序遍历代码。

迭代法前序遍历

迭代法前序遍历代码如下:(「注意此时我们和中序遍历相比仅仅改变了两行代码的顺序」)

class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if (root != NULL) st.push(root);while (!st.empty()) {TreeNode* node = st.top();if (node != NULL) {st.pop();if (node->right) st.push(node->right);  // 右if (node->left) st.push(node->left);    // 左st.push(node);                          // 中st.push(NULL);} else {st.pop();node = st.top();st.pop();result.push_back(node->val);}}return result;}
};

迭代法后序遍历

后续遍历代码如下:(「注意此时我们和中序遍历相比仅仅改变了两行代码的顺序」)

class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if (root != NULL) st.push(root);while (!st.empty()) {TreeNode* node = st.top();if (node != NULL) {st.pop();st.push(node);                          // 中st.push(NULL);if (node->right) st.push(node->right);  // 右if (node->left) st.push(node->left);    // 左} else {st.pop();node = st.top();st.pop();result.push_back(node->val);}}return result;}
};

总结

此时我们写出了统一风格的迭代法,不用在纠结于前序写出来了,中序写不出来的情况了。

但是统一风格的迭代法并不好理解,而且想在面试直接写出来还有难度的。

所以大家根据自己的个人喜好,对于二叉树的前中后序遍历,选择一种自己容易理解的递归和迭代法。

本文:https://github.com/youngyangyang04/leetcode-master​已经收录,里面还有leetcode刷题攻略、各个类型经典题目刷题顺序、思维导图,可以fork到自己仓库,有空看一看一定会有所收获,如果对你有帮助也给一个star支持一下吧!

我的B站(里面有我讲解的算法视频以及编程相关知识):https://space.bilibili.com/525438321

我是程序员Carl,哈工大师兄,先后在腾讯和百度从事技术研发多年,利用工作之余重刷leetcode,更多   精彩算法文章尽在: 代码随想录,关注后,回复「Java」「C++」「python」「简历模板」等等,有我整理多年的学习资料,可以加我  微信,备注「个人简介」+「组队刷题」,拉你进入刷题群(无任何广告,纯个人分享),每天一道经典题目分析,我选的每一道题目都不是孤立的,而是由浅入深一脉相承的,如果跟住节奏每篇连续着看,定会融会贯通。

二叉树:前中后序迭代方式统一写法相关推荐

  1. 二叉树前中后序遍历以及节点计算

    二叉树前中后序遍历以及节点计算 二叉树 分类 二叉链的数据结构 三叉链的数据结构 四种遍历方法 深度优先遍历:前中后序 广度优先遍历:层序遍历 计算 节点个数 叶子节点个数 树的高度 第k层的节点个数 ...

  2. 二叉树前中后序遍历的非递归实现以及层次遍历、zig-zag型遍历详解

    前言 二叉树的遍历是一个比较常见的问题,递归实现二叉树的前中后序遍历比较简单,但非递归实现二叉树的前中后序遍历相对有难度.这篇博客将详述如何使用非递归的方式实现二叉树的前中后序遍历,在进行理论描述的同 ...

  3. 二叉树前中后序遍历+刷题【中】【数据结构/初阶/C语言实现】

    文章目录 1. 二叉树基础操作 1.1 二叉树遍历 1.1.1 前序遍历 前序遍历(Pre-Order Traversal) 1.1.2 中序遍历 中序遍历(In-Order Traversal) 1 ...

  4. 线索二叉树(前中后序线索化/遍历/画线索)

    线索二叉树 文章目录 线索二叉树 1 线索二叉树的基本概念 2 线索二叉树的构造 2.1 线索二叉树的存储结构 2.2 给线索二叉树画线索 2.2.1 中序 2.2.2 先序 2.2.3 后序 2.3 ...

  5. 【霍罗维兹数据结构】二叉树前中后序遍历 | 层序遍历 | 复制二叉树 | 判断两个二叉树全等 | 可满足性问题

    写在前面 学习二叉树结构,最简单的方式就是遍历.所谓二叉树遍历,就是按照某种特定的规则,一次对二叉树中的节点进行相应的操作,并且每个节点只操作一次. 访问节点所做的操作要看具体的应用问题.遍历是二叉树 ...

  6. 二叉树非递归dfs——简单思路搞定前中后序遍历

    前言:相信很多同学都被二叉树非递归dfs的前中后序遍历方法弄的头疼.网上的答案,什么前中后序遍历各有一套写法,还有什么一个栈的写法,两个栈的写法.看起来能理解,一闭眼自己写都记不住.今天介绍一种用一种 ...

  7. LeetCode——树:层次遍历、前中后序遍历

    LeetCode--树:层次遍历.前中后序遍历 目录 层次遍历 二叉树的层平均值 找树左下角的值 前中后序遍历 概述 非递归实现二叉树的前序遍历 非递归实现二叉树的中序遍历 非递归实现二叉树的后序遍历 ...

  8. [Leedcode][JAVA][第94/144/145题][前中后序遍历][递归][迭代][二叉树]

    [问题描述][] 前序遍历 先输出当前结点的数据,再依次遍历输出左结点和右结点 中序遍历 先遍历输出左结点,再输出当前结点的数据,再遍历输出右结点 后续遍历 先遍历输出左结点,再遍历输出右结点,最后输 ...

  9. 二叉树的层序遍历和前中后序遍历代码 迭代/递归

    二叉树的层序遍历和前中后序遍历代码 迭代/递归 只记录代码.思路参考代码随想录:https://github.com/youngyangyang04/leetcode-master/blob/mast ...

  10. 代码随想录——二叉树(一):前中后序遍历,层序遍历,翻转

    题目来自:https://www.programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80. ...

最新文章

  1. 中文版-He Knows My Name(他知道我的名字)-祂认得我-陈熙(音乐河4)
  2. 高并发-【抢红包案例】之二:使用悲观锁方式修复红包超发的bug
  3. hdu 4027(线段树)
  4. 蒙特利尔大学发布2021年最新自监督小样本检测综述
  5. QT多国语言加载qm文件不起效果问题总结
  6. 直接访问 可以拿到cookie 本地起的服务拿不到 cookie_微服务下的分布式session管理...
  7. Android字数限制的EditText实现方案研究
  8. JQUERY弹层|图片滚动|插件开发|上传 相关收藏
  9. 图书管理系统源代码<Java>(带文字讲解)(javase)
  10. matlab opnet,OPNET中设计网络 MATLAB
  11. 光模块发射光功率和接收灵敏度介绍
  12. iphone计算机适配,iPhone UI界面尺寸如何一稿适配
  13. CMM 关键过程域
  14. ideal在编译的时候报程序包不存在错误
  15. cmdb python 采集虚拟机_CMDB学习之八,完成所有资产采集信息的收集
  16. 5-36V输入自动升降压PD快充方案图纸30W低成本芯片
  17. 如何利用社交媒体进行跨境电商营销—扬帆际海
  18. 计算机里的文件丢失6,u盘修复后文件丢失解决方法
  19. virtualbox导入ovf文件
  20. 手机实名认证接口有哪些类别?

热门文章

  1. 笔者带你剖析轻量级Sharding中间件——Kratos1.x
  2. [No00002E]关于大数据,你不知道的6个迷思
  3. springmvc环境的搭建
  4. Spring提供的iBatis的SqlMap配置
  5. [转]python cookielib
  6. 关于hadoop HDFS进行读写文件操作的问题
  7. Linux 切换用户
  8. jqueryEasyui常用代码
  9. office如何去除多页签
  10. php常见错误和解决办法