题目描述:

给定一个二叉树的根节点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)。

二叉树中序遍历的三种方法相关推荐

  1. 二叉树后序遍历的四种方法

    在二叉树三种顺序的遍历中,后序遍历相对较麻烦一些,其实对于递归方法来说,三种方法大同小异,思路与实现都很简单.后序遍历的迭代法与Morris方法比较麻烦.这里介绍后序遍历的四种方法,其实还是递归.迭代 ...

  2. js中map遍历的三种方法

    1.forEach遍历: map.forEach((key,val)=>{...//操作 } key是属性值,val是属性 2.for of遍历: for(let item of map){.. ...

  3. 【C语言】二叉树中序遍历(递归和非递归)算法

    二叉树中序遍历的实现思想是: 访问当前节点的左子树: 访问根节点: 访问当前节点的右子树: 图 1 二叉树 以图  1 为例,采用中序遍历的思想遍历该二叉树的过程为: 访问该二叉树的根节点,找到 1: ...

  4. 【LeetCode 剑指offer刷题】树题19:8 二叉树中序遍历的下一个结点

    [LeetCode & 剑指offer 刷题笔记]目录(持续更新中...) 8 二叉树中序遍历的下一个结点 题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注 ...

  5. c++语言定义排序函数,关于C++中定义比较函数的三种方法小结

    C++编程优与Pascal的原因之一是C++中存在STL(标准模板库).STL存在很多有用的方法. C++模板库中的许多方法都需要相关参数有序,例如Sort().显然,如果你想对一个集合进行排序,你必 ...

  6. 基本题型记录-二叉树中序遍历

    由于本人基础较差,所以针对部分题型做一个记录,以免自己忘记 1.二叉树中序遍历 这个遍历方法可以搜一下博客上很多讲解,这里主要是记录一下代码实现,以下面的二叉树为例子 结果应该是 2.迭代法 2.1 ...

  7. LaTeX 中处理参考文献的三种方法总结

    LaTeX 中处理参考文献的三种方法总结 方法一:用BibLaTeX处理 分成如下四步: 第一步:制作生成bib文件: 第二步:在导言区需要加入biblatex宏包: \usepackage[格式控制 ...

  8. LaTeX中处理参考文献的三种方法总结

    LaTeX 中处理参考文献的三种方法总结 1.摘要 2.关键词 3.处理参考文献常用的三种方法 3.1 方法一:用BibLaTeX处理 3.2 方法二:用BibTeX处理 3.3 方法三:用thebi ...

  9. 二叉树中序遍历(递归+迭代)——java

    目录 一.题目 二.中序遍历讲解 三.中序遍历递归法实现 1.递归思路 2.代码实现 四.中序遍历迭代法实现 1.迭代思路 2.代码实现 五.欢迎访问我的java二叉树专栏 一.题目 1.题目链接:二 ...

最新文章

  1. 73. Leetcode 230. 二叉搜索树中第K小的元素 (二叉搜索树-中序遍历类)
  2. spring cloud bus AMQP学习笔记
  3. activiti搭建
  4. 图片上传压缩android,android 图片上传压缩常见问题分析
  5. 象棋子 设计模式_通过设计国际象棋游戏了解策略模式
  6. Why is processing a sorted array faster than an unsorted array?
  7. ImmuniWeb 推出暗网数据泄露免费查询工具,使用超简单
  8. Java学习笔记(三):数组
  9. 使用Emit创建DBContext对象
  10. 简单之美 | ZooKeeper应用案例
  11. SpreadJS v14.1.5 Crack
  12. 23考研倒计时,冲刺阶段这样做事半功倍!
  13. 阿里云ECS后台CPU占用100%,top却找不到
  14. python相关性分析
  15. dy极速版-艳云脚本云控系统
  16. AI绘画与虚拟人生成实践(二):智能不智障!用chatgpt自动写爆款内容
  17. 机场生产运行数据统计指标-第二篇-航班类
  18. fortify源代码扫描问题分析汇总
  19. 快速gcd vs 普通gcd
  20. 高通平台SSC架构-sensor学习

热门文章

  1. Nginx报错 HTTP 413 Request Entity Too Large(Payload Too Large)解决方案
  2. 太阳辐射标准观测站QY-TYN02
  3. 不要来日本IT业混饭
  4. 韩舜尧 论: JavaScript如何实现省市级联动~(面试宝典必会题之一)
  5. 晶振参数详解及设计参考
  6. 微信小程序如何与数据库交互?
  7. 跨域问题-Refused to display in a frame because it set ‘X-Frame-Options‘ to ‘SAMEORIGIN‘
  8. pycurl的学习之路
  9. 对于串口接收数据有丢包如何处理
  10. ChatGPT 提问技巧