一、前序遍历(迭代法)->右左中

前序遍历是中左右,每次先处理的是中间节点,那么先将根节点放入栈中,然后将右孩子加入栈,再加入左孩子。

为什么要先加入 右孩子,再加入左孩子呢?因为这样出栈的时候才是中左右的顺序。

注:前序遍历要访问的元素和要处理的元素顺序是一致的,都是中间节点

class Solution {public:vector<int> preorderTraversal(TreeNode* root) {vector<int> res;stack<TreeNode*> st;if(root!=nullptr) st.push(root);//将被访问的结点放入栈中while(!st.empty()) //此时栈内不为空{TreeNode *node=st.top();//标记栈顶元素(此时是被访问型元素)if(node!=nullptr)//若栈顶元素不为空{st.pop();//弹出栈顶元素if(node->right!=nullptr) st.push(node->right);//添加右结点(空节点不入栈)if(node->left!=nullptr)  st.push(node->left);//添加左节点(空节点不入栈)st.push(node);//添加已被访问过的中间结点st.push(nullptr);//为此中间结点添加空标记结点//   if(node->left!=nullptr)  st.push(node->left);//添加左节点(空节点不入栈)}else  //当被访问的结点为空节点的时候{st.pop();//弹出空节点node=st.top();//标记将被处理的结点st.pop();res.push_back(node->val);//加入到结果集}}return res;}
};

二.中序遍历(迭代法)->右中左

中序遍历是左中右,先访问的是二叉树顶部的节点,然后一层一层向下访问,直到到达树左面的最底部,再开始处理节点(也就是在把节点的数值放进result数组中),这就造成了处理顺序和访问顺序是不一致的。无法使用栈。

那我们就将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。
如何标记呢,「就是把正在访问的节点放入栈之后,弹出去,把它的右孩子加入栈,再把它自己加入,并且附带一个空指针作为标记,再把左孩子加入栈,此时栈顶元素就是将要被访问的结点,再次重复以上步骤,直到全部结点都已入栈。」 这种方法也可以叫做标记法

class Solution {public:vector<int> preorderTraversal(TreeNode* root) {vector<int> res;stack<TreeNode*> st;if(root!=nullptr) st.push(root);//将被访问的结点放入栈中while(!st.empty()) //此时栈内不为空{TreeNode *node=st.top();//标记栈顶元素(此时是被访问型元素)if(node!=nullptr)//若栈顶元素不为空{st.pop();//弹出栈顶元素if(node->right!=nullptr) st.push(node->right);//添加右结点(空节点不入栈)st.push(node);//添加已被访问过的中间结点st.push(nullptr);//为此中间结点添加空标记结点if(node->left!=nullptr)  st.push(node->left);//添加左节点(空节点不入栈)}else  //当被访问的结点为空节点的时候{st.pop();//弹出空节点node=st.top();//标记将被处理的结点st.pop();res.push_back(node->val);//加入到结果集}}return res;}
};

三、后序遍历(迭代法)->中右左

class Solution {public:vector<int> postorderTraversal(TreeNode* root) {vector<int> res;stack<TreeNode*> st;if(root!=nullptr) st.push(root);//将被访问的结点放入栈中while(!st.empty()) //此时栈内不为空{TreeNode *node=st.top();//标记栈顶元素(此时是被访问型元素)if(node!=nullptr)//若栈顶元素不为空{st.pop();//弹出栈顶元素st.push(node);//添加已被访问过的中间结点st.push(nullptr);//为此中间结点添加空标记结点if(node->right!=nullptr) st.push(node->right);//添加右结点(空节点不入栈)if(node->left!=nullptr)  st.push(node->left);//添加左节点(空节点不入栈)}else  //当被访问的结点为空节点的时候{st.pop();//弹出空节点node=st.top();//标记将被处理的结点st.pop();res.push_back(node->val);//加入到结果集}}return res;}
};

总结

只要理解3点:以中序遍历为例

1.栈的特性入栈和出栈顺序相反,想要输出顺序"左中右",入栈顺序必须按照"右中左"。
2.入栈的处理:可以把整颗树简化为3个节点一组的多个子树。即(父节点,左孩子,右孩子)这3个节点组成的子树。每次循环处理的实际就是将这样的3个节点按照规则顺序(右中左)进行入栈。所以才有了代码中看到的:每次都是先将栈顶元素去除,然后对以栈顶元素做为父节点的3个节点子树按规则顺序(右中左)入栈。
3.NULL节点的加入和出栈规则的规定:保证了当左孩子作为栈顶元素时,不会立即出栈,而是会将当前的左孩子(即栈顶元素)作为下次遍历的父节点接着按照规则顺序入栈。直到当前的左孩子做为父节点再无孩子时(无孩子时,入栈规则就成了(父节点,NULL节点)),遇到NULL节点了,才进行出栈。这样就保证了左孩子先出栈啦

二叉树的前中后序遍历之迭代法(统一风格迭代方式)相关推荐

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

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

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

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

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

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

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

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

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

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

  6. 二叉树的前中后序遍历(考试常考)

    二叉树遍历的概念 二叉树的遍历是按某种规则对二叉树的每个节点均只被访问一次,根据根节点访问位置的不同分为三种:先序遍历(根左右).中序遍历(左根右).后序遍历(左右根).         由于树是通过 ...

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

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

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

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

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

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

最新文章

  1. 区块链学习路线及资料索引
  2. [bzoj2839]集合计数 题解 (组合数+容斥)
  3. STM32高级开发(12)-在GCC中使用printf打印串口数据
  4. AVFoundation之录音及播放
  5. redis 图片2进制保存_Redis数据结构底层的SDS了解吗
  6. EnvironmentError: mysql_config not found
  7. office移动端_阿里云 Teambition 网盘产品快讯:移动端正式版即将上线,体验将大幅提升...
  8. 【报告分享】2021年BrandGrow中国新锐品牌增长潜力报告.pdf(附下载链接)
  9. Python 函数式编程,从入门到放弃
  10. 线性判别用于提取词向量_历年试题公开 | 2017级线性代数(I)期末试题
  11. 新版的Eclipse(Oxygen)安装完Subversive后,现时无法自动安装SVN Connector,无论选择哪个都会自动关闭。
  12. 计算机键盘调亮度,电脑屏幕亮度怎么调
  13. 现代数字图像处理作业----对lena.bmp图像采用高频强调滤波增强方法,并分析方法的效果。(理想、巴特沃斯、高斯) 其结果好不好?能否有改善的方法?
  14. Java调用regester命令
  15. win7系统怎样开启wmi服务器,WMI服务是什么?Win7系统如何禁用WMI服务?
  16. Android - 手机下载的缓存视频在文件管理怎么找不到?
  17. PC微信更改文件默认保存位置后聊天记录丢失
  18. 查看windows系统许可证过期日期方法
  19. 修改jar 注入_ORA00600[16703]安装介质注入型勒索病毒恢复案例
  20. JAVA SE程序设计及实践

热门文章

  1. 【工具】克隆题库(适用于所有以POJ2005-2017为模板的OJ平台)
  2. 在ubuntu 14.04 编译android 2.3.1 错误解决办法
  3. grunt前端构建工具使用教程
  4. 深入grootJs(进阶教程)
  5. 解决cell循环利用造成的重复勾选
  6. 企业组织机构代码验证JavaScript版和Java版 - 修正版V20090214
  7. 新建学生类,分别计算3个科目的总和
  8. [Python人工智能] 二十七.基于BiLSTM-CRF的医学命名实体识别研究(下)模型构建
  9. iOS之深入解析内存分配的五大区
  10. iOS实现“下雨下雪”动画效果和“烟花”动画效果