二叉树中序遍历的三种方法
题目描述:
给定一个二叉树的根节点root,返回它的中序遍历。
方法一:递归
思路与算法:
二叉树的中序遍历:按照访问左子树-根节点-右子树的方式遍历这棵树,而在访问左子树或者右子树的时候我们按照同样的方式遍历,直到遍历这棵树,而在访问左子树或者右子树的时候我们按照同样的方式遍历,直到遍历完整棵树。因此整个遍历过程天然具有递归性质,我们可以直接用递归函数来模拟这一过程。
定义inorder(root)表示当前遍历到root节点的答案,那么按照定义,我们只要递归调用inorder(root.left)来遍历root节点的左子树,然后将root节点的值加入答案,在递归调用inorder(root.right)来遍历root节点的右子树即可,递归终止的条件为碰到空节点。
java实现:
/*** 二叉树的中序遍历 : 递归方法* @param root : 二叉树* @return : 中序遍历结果*/public List<Integer> inorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<>();inorder(root, res);return res;}public void inorder(TreeNode root, List<Integer> res) {if (root == null)return;inorder(root.left, res);res.add(root.val);inorder(root.right, res);}
算法分析:
- 时间复杂度:O(n),其中n为二叉树节点的个数,二叉树的遍历中每个节点会被访问一次且只被访问一次。
- 空间复杂度:O(n),空间复杂度取决于递归栈的深度,而栈深度在二叉树为一条链的情况下会达到O(n)的级别。
方法二:迭代法
算法思路:
方法一的递归函数也可以用迭代的方式实现,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其他都相同,具体实现可以看下面的代码:
java实现:
public List<Integer> stackTraversal(TreeNode root) {List<Integer> res = new ArrayList<>();Deque<TreeNode> stk = new LinkedList<>();// 循环条件,结点不为空并且栈不为空while (root != null || !stk.isEmpty()) {while (root != null) {stk.push(root);root = root.left;}root = stk.pop();res.add(root.val);root = root.right;}return res;}
算法分析:
- 时间复杂度:O(n),其中n为二叉树的节点的个数,二叉树的遍历中每个节点会被访问一次且只访问一次。
- 空间复杂度:O(n),空间复杂度取决于递归栈的深度,而栈深度在二叉树为一条链的情况下会达到O(n)的级别。
方法三:Morris中序遍历
思路与算法:
Morris 遍历算法是另一种遍历二叉树的方法,它能将非递归的中序遍历空间复杂度降为 O(1)。
Morris 遍历算法整体步骤如下(假设当前遍历到的节点为 x):
- 如果 x 无左孩子,先将 xx的值加入答案数组,再访问 x 的右孩子,即 x = x.right。
- 如果 x 有左孩子,则找到 x 左子树上最右的节点(即左子树中序遍历的最后一个节点,x 在中序遍历中的前驱节点),我们记为 predecessor。根据predecessor 的右孩子是否为空,进行如下操作。
- 如果 predecessor 的右孩子为空,则将其右孩子指向 x,然后访问 x 的左孩子,即 x = x.left。
- 如果 predecessor 的右孩子不为空,则此时其右孩子指向 x,说明我们已经遍历完 x 的左子树,我们将 predecessor 的右孩子置空,将 x的值加入答案数组,然后访问 x 的右孩子,即 x=x.right。
重复上述操作,直至访问完整棵树。
java实现:
public List<Integer> inorderTraversal(TreeNode root) {List<Integer> res = new ArrayList<Integer>();TreeNode predecessor = null;while (root != null) {if (root.left != null) {// predecessor 节点就是当前 root 节点向左走一步,然后一直向右走至无法走为止predecessor = root.left;while (predecessor.right != null && predecessor.right != root) {predecessor = predecessor.right;}// 让 predecessor 的右指针指向 root,继续遍历左子树if (predecessor.right == null) {predecessor.right = root;root = root.left;}// 说明左子树已经访问完了,我们需要断开链接else {res.add(root.val);predecessor.right = null;root = root.right;}}// 如果没有左孩子,则直接访问右孩子else {res.add(root.val);root = root.right;}}return res;}
算法分析:
- 时间复杂度:O(n),其中n为二叉搜索树的节点个数,Morris遍历中每个节点会被访问两次,因此总时间复杂度为O(2n) = O(n)。
- 空间复杂度:O(1)。
二叉树中序遍历的三种方法相关推荐
- 二叉树后序遍历的四种方法
在二叉树三种顺序的遍历中,后序遍历相对较麻烦一些,其实对于递归方法来说,三种方法大同小异,思路与实现都很简单.后序遍历的迭代法与Morris方法比较麻烦.这里介绍后序遍历的四种方法,其实还是递归.迭代 ...
- js中map遍历的三种方法
1.forEach遍历: map.forEach((key,val)=>{...//操作 } key是属性值,val是属性 2.for of遍历: for(let item of map){.. ...
- 【C语言】二叉树中序遍历(递归和非递归)算法
二叉树中序遍历的实现思想是: 访问当前节点的左子树: 访问根节点: 访问当前节点的右子树: 图 1 二叉树 以图 1 为例,采用中序遍历的思想遍历该二叉树的过程为: 访问该二叉树的根节点,找到 1: ...
- 【LeetCode 剑指offer刷题】树题19:8 二叉树中序遍历的下一个结点
[LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 8 二叉树中序遍历的下一个结点 题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注 ...
- c++语言定义排序函数,关于C++中定义比较函数的三种方法小结
C++编程优与Pascal的原因之一是C++中存在STL(标准模板库).STL存在很多有用的方法. C++模板库中的许多方法都需要相关参数有序,例如Sort().显然,如果你想对一个集合进行排序,你必 ...
- 基本题型记录-二叉树中序遍历
由于本人基础较差,所以针对部分题型做一个记录,以免自己忘记 1.二叉树中序遍历 这个遍历方法可以搜一下博客上很多讲解,这里主要是记录一下代码实现,以下面的二叉树为例子 结果应该是 2.迭代法 2.1 ...
- LaTeX 中处理参考文献的三种方法总结
LaTeX 中处理参考文献的三种方法总结 方法一:用BibLaTeX处理 分成如下四步: 第一步:制作生成bib文件: 第二步:在导言区需要加入biblatex宏包: \usepackage[格式控制 ...
- LaTeX中处理参考文献的三种方法总结
LaTeX 中处理参考文献的三种方法总结 1.摘要 2.关键词 3.处理参考文献常用的三种方法 3.1 方法一:用BibLaTeX处理 3.2 方法二:用BibTeX处理 3.3 方法三:用thebi ...
- 二叉树中序遍历(递归+迭代)——java
目录 一.题目 二.中序遍历讲解 三.中序遍历递归法实现 1.递归思路 2.代码实现 四.中序遍历迭代法实现 1.迭代思路 2.代码实现 五.欢迎访问我的java二叉树专栏 一.题目 1.题目链接:二 ...
最新文章
- 73. Leetcode 230. 二叉搜索树中第K小的元素 (二叉搜索树-中序遍历类)
- spring cloud bus AMQP学习笔记
- activiti搭建
- 图片上传压缩android,android 图片上传压缩常见问题分析
- 象棋子 设计模式_通过设计国际象棋游戏了解策略模式
- Why is processing a sorted array faster than an unsorted array?
- ImmuniWeb 推出暗网数据泄露免费查询工具,使用超简单
- Java学习笔记(三):数组
- 使用Emit创建DBContext对象
- 简单之美 | ZooKeeper应用案例
- SpreadJS v14.1.5 Crack
- 23考研倒计时,冲刺阶段这样做事半功倍!
- 阿里云ECS后台CPU占用100%,top却找不到
- python相关性分析
- dy极速版-艳云脚本云控系统
- AI绘画与虚拟人生成实践(二):智能不智障!用chatgpt自动写爆款内容
- 机场生产运行数据统计指标-第二篇-航班类
- fortify源代码扫描问题分析汇总
- 快速gcd vs 普通gcd
- 高通平台SSC架构-sensor学习
热门文章
- Nginx报错 HTTP 413 Request Entity Too Large(Payload Too Large)解决方案
- 太阳辐射标准观测站QY-TYN02
- 不要来日本IT业混饭
- 韩舜尧 论: JavaScript如何实现省市级联动~(面试宝典必会题之一)
- 晶振参数详解及设计参考
- 微信小程序如何与数据库交互?
- 跨域问题-Refused to display in a frame because it set ‘X-Frame-Options‘ to ‘SAMEORIGIN‘
- pycurl的学习之路
- 对于串口接收数据有丢包如何处理
- ChatGPT 提问技巧