树的中序遍历(递归,迭代,莫里斯)
所有涉及到中序遍历的题都可以使用该模板解决
中序遍历(inorderTraversal)有递归,迭代,莫里斯三种解法
递归版
public List<Integer> inorderTraversal(TreeNode root) {//具体的细节可以和这里不一样,但思路一致即可,就是左子树递归->root->右子树递归List<Integer> ans = new ArrayList<>();getAns(root, ans);return ans;
}private void getAns(TreeNode node, List<Integer> ans) {if (node == null) {return;}getAns(node.left, ans); ans.add(node.val);getAns(node.right, ans);
}
时间复杂度:O(n),遍历每个节点。
空间复杂度:O(h),压栈消耗,h 是二叉树的高度。
迭代版
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(cur != null || !stack.isEmpty()){while(cur != null){stack.push(cur);cur = cur.left;}cur = stack.pop();/** do something **/cur = cur.right;
}
时间复杂度:O(n)。
空间复杂度:O(h),栈消耗,h 是二叉树的高度。
Morris遍历
解法一和解法二本质上是一致的,都需要 O(h)的空间来保存上一层的信息。而我们注意到中序遍历,就是遍历完左子树,然后遍历根节点。如果我们把当前根节点存起来,然后遍历左子树,左子树遍历完以后回到当前根节点cur就可以了,怎么做到呢?
我们注意到左子树cur.left最右边的节点last的右孩子是null,我们可以将last.right = cur即保留当前根节点即可,这样我们遍历完左子树,就可以回到根节点了。
如果当前根节点的左子树为null,那我们就直接遍历根节点,再考虑右子树cur = cur.right;
所以总体思想就是:记当前遍历的节点为 cur:
- cur.left 为null,保存cur的值,更新cur为cur.right;
- cur.left不为null,记prev = cur.left,找到左子树的最右边节点记为last;
- 如果last.right为null,将last.right = cur;更新cur = cur.left;
- 如果last.right不为null,说明之前已经访问过,第二次来到这里,表明当前子树遍历完成,将last.right = null;保存cur的值,更新cur为cur.right。
结合图示:
如上图,cur 指向根节点。 当前属于 3 的情况,cur.left 不为 null,cur 的左子树最右边的节点的右孩子为 null,那么我们把最右边的节点的右孩子指向 cur。
接着,更新 cur = cur.left。
如上图,当前属于 3 的情况,cur.left 不为 null,cur 的左子树最右边的节点的右孩子为 null,那么我们把最右边的节点的右孩子指向 cur。
更新 cur = cur.left。
如上图,当前属于情况 1,cur.left 为 null,保存 cur 的值,更新 cur = cur.right。
如上图,当前属于 4 的情况,cur.left 不为 null,cur 的左子树最右边的节点的右孩子已经指向 cur,保存 cur 的值,更新 cur = cur.right。
如上图,当前属于情况 1,cur.left 为 null,保存 cur 的值,更新 cur = cur.right。
如上图,当前属于4的情况,cur.left 不为 null,cur 的左子树最右边的节点的右孩子已经指向 cur,保存 cur 的值,更新 cur = cur.right。
当前属于情况 1,cur.left 为 null,保存 cur 的值,更新 cur = cur.right。
cur 指向 null,结束遍历。
根据这个关系,写代码:
public List<Integer> inorderTraversal(TreeNode root) {List<Integer> ans = new ArrayList<>();TreeNode cur = root;while(cur != null){if(cur.left == null){ans.add(cur.val); //do somethingcur = cur.right;}else{TreeNode prev = cur.left;while(prev.right != null && prev.right != cur)prev = prev.right;//情况3 if(prev.right == null){prev.right = cur;cur = cur.left;} //情况4,不用担心前一个if会影响后一个,因为cur已经改变了if(prev.right == cur){prev.right = null;ans.add(cur.val); //do somethingcur = cur.right;}}}return ans; //依据实际情况返回
时间复杂度:O(n)。每个节点遍历常数次。
空间复杂度:O(1)。
树的中序遍历(递归,迭代,莫里斯)相关推荐
- 二叉树的中序遍历 [递归 迭代]
中序遍历的递归 & 迭代 前言 一.二叉树的中序遍历 二.递归 & 迭代 1.递归版 2.迭代(断左子树版) 3.迭代(root迭代版) 4.mirror(O(1)空间版) 总结 参考 ...
- LeetCode 94. 二叉树的中序遍历(递归)(迭代)(颜色标记法)
题目描述 给定一个二叉树,返回它的后序遍历 思路 详见链接 代码 递归 #class TreeNode: # def __init__(self,x): # self.val = x # self.l ...
- 怎样将树的中序遍历的数输入到一个数组中_数据结构与算法-二叉查找树平衡(DSW)...
上一节探讨了二叉查找树的基本操作,二叉查找树的查找效率在理想状态下是O(lgn),使用该树进行查找总是比链表快得多.但是,该论点并不总是正确,因为查找效率和二叉树的形状息息相关.就像这样: 图1-1给 ...
- Morris遍历算法 树的中序遍历
Morris遍历算法 树的中序遍历 树的中序遍历 一.普通方法 1.递归实现 2.栈实现 二.Morris遍历 1.算法 2.代码 总结 树的中序遍历 对于当前结点,先输出它的左孩子,然后输出该结点, ...
- 为什么普通树没有中序遍历和森林没有后序遍历
本文为个人理解,若有错误欢迎指正! 这里说的树当然是指普通的树,而不是树中比较特别的二叉树. 1.为什么普通树没有中序遍历 中序遍历是对于二叉树而言: 中序遍历左子树,访问根结点,中序遍历右结点. 在 ...
- 数据结构二叉树中序遍历递归和非递归算法
2022.11.19 二叉树中序遍历递归和非递归算法 任务描述 相关知识 编程要求 测试说明 C/C++代码 任务描述 本关任务:给定一棵二叉树,使用递归和非递归的方法实现二叉树的中序遍历结果. 相关 ...
- LeetCode 94. Binary Tree Inorder Traversal--二叉树中序遍历--递归,迭代--C++,Python解法
题目地址:Binary Tree Inorder Traversal - LeetCode Given a binary tree, return the inorder traversal of i ...
- [Leedcode][JAVA][第94/144/145题][前中后序遍历][递归][迭代][二叉树]
[问题描述][] 前序遍历 先输出当前结点的数据,再依次遍历输出左结点和右结点 中序遍历 先遍历输出左结点,再输出当前结点的数据,再遍历输出右结点 后续遍历 先遍历输出左结点,再遍历输出右结点,最后输 ...
- 剑指offer面试题36. 二叉搜索树与双向链表(中序遍历)(递归)
题目描述 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表.要求不能创建任何新的节点,只能调整树中节点指针的指向. 思路 详见链接 代码 #class Node: # def __ini ...
- 二叉树的中序遍历 递归与非递归
94. 二叉树的中序遍历 给定一个二叉树的根节点 root ,返回它的 中序 遍历. 示例 1: 输入:root = [1,null,2,3] 输出:[1,3,2] 示例 2: 输入:root = [ ...
最新文章
- python个人项目-软工作业个人项目wc.exe(python实现)
- 技巧: 用 JAXM 发送和接收 SOAP 消息—Java API 使许多手工生成和发送消息方面必需的步骤自动化...
- 卸载重装svn后原来项目不受管理,版本不对应还是,升级工作副本解决?
- 使用jQuery实现图片懒加载原理
- angularjs 整合bootstrap 时间控件
- Pytorch基础(三)—— DataSet的应用
- RHEL 5服务篇—常用网络配置命令
- 为什么说黄桃罐头是东北的人参果
- ComboBox信息读取
- 利用AjaxPro从客户端调用服务端函数的方法
- Flink on Zeppelin (3) - Streaming 篇
- 中国人工智能学会通讯——一种基于众包的交互式数据修复方法 3 给定质量约束下的交互式算法...
- Word排版艺术 读后感
- Open Cube 时信魔方介绍
- 最小二乘法算法C语言,最小二乘法C算法终极整理版本,绝对原创!
- [电影]《指环王》新老三部曲完全赏析(王者归来)
- c语言实例--打渔晒网问题
- [前端]-- jquery学习1
- 移动路由器做网站服务器,移动路由器上网方式选哪个?
- KT148A语音芯片ic的硬件设计注意事项
热门文章
- Mac OS X Safari 插件存放位置
- 电脑仙人掌机器人作文_蜗牛、仙人掌、电脑、雪人、机器人、蚕宝宝、大象选三到四个词作文...
- Linux就这个范儿 第16章 谁都可以从头再来--从头开始编译一套Linux系统 nsswitch.conf配置文件...
- 技术可行性与操作可行性的资料搜集与分析
- Android adb截图后保存到电脑
- 华氏温度转换为摄氏温度,c语言实例一
- 最新matlab音乐合成实验报告,Matlab音乐合成实验报告
- C#读取文本框(TextBox)数据并统计其中最大小值平均值及求出所在数组中位置,在文本框中显示
- 深圳大学计算机系在哪个校区,2021年深圳大学有几个校区,大一新生在哪个校区...
- Android 利用重力感应调整手机模式