文章目录

  • 1 题目
  • 2 描述
  • 3 解决方案
    • 3.1 递归算法
      • 3.1.1 遍历法(Traverse)
        • 思路
        • 源码
      • 3.1.2 分治法(Devide And Conquer)
        • 思路
        • 源码
    • 3.2 非递归算法
      • 3.2.1 二叉树遍历的非递归通用解法
        • 思路
        • 源码
        • 图解
    • 3.3 时间复杂度
    • 3.4 空间复杂度

1 题目

  二叉树的中序遍历(Binary Tree Inorder Traversal)

lintcode:题号——67,难度——easy

2 描述

  给出一棵二叉树,返回其节点值的中序遍历。

名词:

遍历

按照一定的顺序对树中所有节点进行访问的过程叫做树的遍历。

中序遍历

在二叉树中,首先遍历左子树,然后访问根结点,最后遍历右子树,在遍历左右子树时,仍然采用这种规则,这样的遍历方式叫做二叉树的中序遍历。

序列化规则:

使用大括号包裹节点序列来表示二叉树,首个数据为根节点,后面接着是其左儿子和右儿子节点值,"#"表示不存在该子节点,之后以此类推。

样例1:

输入:二叉树 = {1,2,3}
输出:[2,1,3]
解释:上述{1,2,3}序列按照序列化规则表示的二叉树如下

     1/ \2   3

按照前序遍历规则,先根再左右子树,顺序即为[2,1,3]

样例2:

输入:二叉树 = {1,#,2,3}
输出:[1,3,2]
解释:上述{1,#,2,3}序列按照序列化规则表示的二叉树如下

        1/   \#       2/3

按照前序遍历规则,先根再左右子树,顺序同样为[1,3,2]

3 解决方案

  中序遍历与前序遍历1一样可以使用递归和非递归两类方式,递归和非递归各自的优缺点在前序遍历中也提到了。

3.1 递归算法

  递归写法比较简单,主要注意防止死循环,递归的过程中要明确递归的三要素。

递归的三要素:

  1. 递归的定义(递归函数的返回值、参数要如何定义)
  2. 递归的拆解(递归如何向下拆分)
  3. 递归的出口(递归的结束条件)

  递归又有两种形式,遍历和分治。

3.1.1 遍历法(Traverse)

思路

  遍历的整个过程可以看成是为了完成某项大任务,于是领导亲自下基层处理各项小任务,所有工作都“亲历亲为”,参与了所有工作最终完成了大任务。

遍历法的主要递归函数一般不带返回值,会拥有全局参数或者贯穿整个递归过程的函数参数用来处理数据。

源码

  C++版本:

/**
* @param root: A Tree
* @return: Inorder in ArrayList which contains node values.
*/
vector<int> inorderTraversal(TreeNode * root) {// write your code herevector<int> result;traverse(root, result);return result;
}// 遍历法的递归函数,没有返回值,函数参数result贯穿整个递归过程用来记录遍历的结果
void traverse(TreeNode * cur, vector<int> & result) // 递归三要素之定义
{if (cur == nullptr){return; // 递归三要素之出口}// 此处与前序遍历不同,先处理左子树,再处理根节点,最后处理右子树traverse(cur->left, result); // 递归三要素之拆解result.push_back(cur->val);traverse(cur->right, result);
}

3.1.2 分治法(Devide And Conquer)

思路

  分治法的整个过程可以看成是为了完成某项大人物,于是领导把各项工作分派给各个下属,各个下属又把工作继续细分层层向下分派给基层人员,每一级都只需要获取下级完成的任务结果即可,最终所有层级任务都完成了,大任务也对应完成了。

分治法的主要递归函数一般需要有返回值,用来向上一层提供结果。

源码

  C++版本:

/**
* @param root: A Tree
* @return: Inorder in ArrayList which contains node values.
*/
// 由于主函数的形式已经符合分治法需要的形式(具有合适的返回值),直接使用主函数做为递归函数
vector<int> inorderTraversal(TreeNode * root) {// write your code herevector<int> result;if (root == nullptr){return result; // 递归三要素之出口}// 获取左子树的遍历结果vector<int> leftResult = inorderTraversal(root->left); // 递归三要素之拆解// 获取右子树的遍历结果vector<int> rightResult = inorderTraversal(root->right);// 此处与前序遍历不同,先处理左子树,再处理根节点,最后处理右子树result.insert(result.end(), leftResult.begin(), leftResult.end());result.push_back(root->val);result.insert(result.end(), rightResult.begin(), rightResult.end());return result;
}

3.2 非递归算法

3.2.1 二叉树遍历的非递归通用解法

思路

  在中序遍历的非递归算法中,与前序遍历1唯一的不同之处在于对节点的解析操作发生的时刻,前序遍历是“边入栈边解析”,而中序遍历是“出栈时解析”。

  1. 左穿入栈到底;
  2. 从栈内弹出当前节点,可能是左子树或者根节点(相对),出栈时解析;
  3. 右子树的根节点入栈,重复1、2步骤(即对右子树做中序遍历),直到满足循环结束条件,该二叉树的中序遍历即在结果序列中。

中序遍历的初始条件和循环结束条件在通用解法中与前序遍历一致。
初始条件:栈为空当前指针指向根节点
循环结束条件:栈为空当前指针为空

源码
/**
* @param root: A Tree
* @return: Inorder in ArrayList which contains node values.
*/
vector<int> inorderTraversal(TreeNode * root) {// write your code herevector<int> result;if (root == nullptr){return result;}stack<TreeNode *> nodeStack;TreeNode * cur = root;while (!nodeStack.empty() || cur != nullptr){while (cur != nullptr){nodeStack.push(cur);cur = cur->left;}cur = nodeStack.top();result.push_back(cur->val); // 此处是通用解法中唯一与前序遍历不同的地方,出栈时解析nodeStack.pop();cur = cur->right;}return result;
}
图解

  在解法中,中序遍历的过程与前序遍历1基本一致,可以参考前序遍历的图解,区别只是解析操作发生的时刻不同。

3.3 时间复杂度

  对二叉树的遍历,不管使用什么方式都是将整棵树中的所有节点走一遍,所以算法的时间复杂度都为O(n)。

  关于二叉树和分治法的时间复杂度的更多内容,在前序遍历1中已经进行了计算分析。

3.4 空间复杂度

  算法的空间复杂度,分治法为O(n),上述其余方法都为O(1)。


  1. 二叉树的前序遍历:https://blog.csdn.net/SeeDoubleU/article/details/119834420 ↩︎ ↩︎ ↩︎ ↩︎

15 二叉树的中序遍历(Binary Tree Inorder Traversal)相关推荐

  1. 【二叉树迭代版中序遍历】LeetCode 94. Binary Tree Inorder Traversal

    LeetCode 94. Binary Tree Inorder Traversal Solution1:递归版 二叉树的中序遍历递归版是很简单的,中序遍历的迭代版需要特殊记一下! 迭代版链接:htt ...

  2. LeetCode-二叉树-94. 二叉树的中序遍历

    描述 94. 二叉树的中序遍历 给定一个二叉树的根节点 root ,返回它的 中序 遍历. 示例 1: 输入:root = [1,null,2,3] 输出:[1,3,2] 示例 2: 输入:root ...

  3. LeetCode 92反转链表Ⅱ93复制ip地址94二叉树的中序遍历

    微信搜一搜:bigsai 专注于Java.数据结构与算法,一起进大厂不迷路! 算法文章题解全部收录在github仓库bigsai-algorithm,求star! 关注回复进群即可加入力扣打卡群,欢迎 ...

  4. lintcode:二叉树的中序遍历

    题目: 二叉树的中序遍历 给出一棵二叉树,返回其中序遍历 样例 给出二叉树 {1,#,2,3}, 1\2/3 返回 [1,3,2]. 挑战 你能使用非递归算法来实现么? 解题: 程序直接来源 Java ...

  5. 二叉树的中序遍历 [递归 迭代]

    中序遍历的递归 & 迭代 前言 一.二叉树的中序遍历 二.递归 & 迭代 1.递归版 2.迭代(断左子树版) 3.迭代(root迭代版) 4.mirror(O(1)空间版) 总结 参考 ...

  6. 每日一题——二叉树的中序遍历

    菜鸡每日一题系列打卡94天 每天一道算法题目 小伙伴们一起留言打卡 坚持就是胜利,我们一起努力! 题目描述(引自LeetCode) 给定一个二叉树,返回它的中序遍历. 示例: 输入: [1,null, ...

  7. 94. 二叉树的中序遍历

    94. 二叉树的中序遍历 难度中等902收藏分享切换为英文接收动态反馈 给定一个二叉树的根节点 root ,返回它的 中序 遍历. 示例 1: 输入:root = [1,null,2,3] 输出:[1 ...

  8. 树结构练习——排序二叉树的中序遍历(二叉搜索树)

    树结构练习--排序二叉树的中序遍历 Time Limit: 1000MS Memory limit: 65536K 题目描述 在树结构中,有一种特殊的二叉树叫做排序二叉树,直观的理解就是--(1).每 ...

  9. 树结构练习——排序二叉树的中序遍历

    树结构练习--排序二叉树的中序遍历 Description 在树结构中,有一种特殊的二叉树叫做排序二叉树,直观的理解就是--(1).每个节点中包含有一个关键值 (2).任意一个节点的左子树(如果存在的 ...

最新文章

  1. 前端渐进式框架Vue讲解
  2. FaaS — Serverless — 实现原理
  3. create-react-app的template和assembed resource
  4. Spring常用注解的讲解
  5. poj2229 基础的动态规划算法 挑战程序设计竞赛
  6. docker宿主机访问容器_Docker容器与宿主机器通过IP内外通讯
  7. 2021高通人工智能应用创新大赛踩坑指南
  8. 第四(装饰器、迭代器、生成器)
  9. 更改appstore开发商名字
  10. Jquery实现图片的预加载与延时加载
  11. Atitit 第三方登录与sso单点登录 单点登录:       我们的单点登录系统,主要包含了登录验证,token校验 、注销、注册几大功能,单点登录系统提供了统一的登录和注册页面,提供了统一的
  12. mac 安装 android 系统,苹果电脑Mac系统如何安装Android模拟器?
  13. java ssm框架项目_3个SSM框架应用实例教程
  14. 如何设置input只能输入数字
  15. javascript网页特效(一)
  16. 2021年美容师(初级)考试资料及美容师(初级)
  17. 网文快搜——职业生涯
  18. Python常见问题解决办法汇总
  19. 爬取虎扑nba球员得分榜信息并存储至MongoDB数据库
  20. 静态链表(C++实现)——基于数据结构(沈俊版)(初学者食用)

热门文章

  1. Android Studio补间动画
  2. VS+Qt — Vistual Studio 2022+Qt6安装教程以及解决Qt Vistual Studio Tools下载慢和VS无法打开.ui进行设计的问题
  3. hdu1495非常可乐
  4. 原生Javascript(数组操作方法总结)-更新
  5. vue简单实现购物车
  6. fabs函数 与 if else函数 性能测试
  7. 苹果手机速度慢_苹果MagSafe 磁吸充电器的用户请注意这几个潜在问题
  8. 百度反击 代理商已弃用360产品
  9. PVA超细颗粒清洗现象
  10. JavaScript 对象字面量