中序遍历

一、中序遍历概述

中序遍历(Inorder Traversal)是二叉树遍历的一种方式,遍历顺序为:左子树 -> 根节点 -> 右子树。这种遍历方式常用于二叉搜索树,可以得到一个升序排列的节点序列。

二、解决方式

第一种方法--递归实现

思路分析

  1. 递归终止条件:当前节点为null时返回
  2. 递归过程
    • 先递归遍历左子树
    • 访问当前节点(将值加入列表)
    • 再递归遍历右子树
  3. 特点:利用系统调用栈实现回溯,代码简洁易懂
    public List<Integer> inorderTraversal1(TreeNode root) {
        //使用递归方式,返回值是列表,所以需要列表存储,递归的思想是回溯,从叶子节点回溯,而终止条件就是叶子结点为空的时候,返回
        List<Integer> list = new ArrayList<>();
        //使用一个辅助方法来递归
        inoederHelper(root, list);
        return list;
    }
    private void inoederHelper(TreeNode current, List list){
        //终止条件
        if (current == null){
            return;
        }
        //遍历左子树
        inoederHelper(current.left, list);
        //得到回溯的节点,也就是第一个叶子结点,将当前结点添加到列表中
        list.add(current.val);
        //遍历右子树
        inoederHelper(current.right,list);
    }

时间复杂度

  • O(n),每个节点都会被访问一次

空间复杂度

 

  • 最坏情况下O(n)(树退化为链表时)
  • 平均情况下O(h),h为树的高度

第二种方法--迭代实现

思路分析

 

  1. 使用栈模拟递归:显式地使用栈来代替递归中的系统调用栈
  2. 算法步骤
    • 从根节点开始,将所有左子节点入栈
    • 弹出栈顶元素(最左节点)并访问
    • 转向该节点的右子树,重复上述过程
  3. 循环条件:当前节点不为空或栈不为空
    • 当前节点不为空:说明还有左子树需要处理
    • 栈不为空:说明还有节点需要访问
//使用迭代遍历,思想是利用栈先进后出的原则,从上到下迭代遍历,(从左节点开始)将当前结点入栈,当左子树遍历完后(左节点不为空),出栈,先出的就是左子树的叶子结点了
    //就可以实现中序遍历的思想,使用while循环,以栈是否为空判断退出循环。使用列表存储节点
    public List<Integer> inorderTraversal2(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode current = root;
        while (current != null || !stack.isEmpty()){
            //遍历左子树
            while (current != null){
                stack.push(current);//入栈
                current = current.left;
            }
            //出栈
            current = stack.pop();
            list.add(current.val);
            //遍历右子树
            current = current.right;
        }
        return list;
    }

时间复杂度

  • O(n),每个节点都会被访问一次

空间复杂度

 

  • O(h),h为树的高度,栈的最大深度等于树的高度

 

测试用例

[1,null,2,3]

输出结果

[1,3,2]

[1,null,2,3]

[1,null,2,3]

 

# 中序遍历学习笔记
## 一、中序遍历概述
中序遍历(Inorder Traversal)是二叉树遍历的一种方式,遍历顺序为:左子树 -> 根节点 -> 右子树。这种遍历方式常用于二叉搜索树,可以得到一个升序排列的节点序列。
## 二、递归实现
### 代码实现```javapublic List<Integer> inorderTraversal1(TreeNode root) {    List<Integer> list = new ArrayList<>();    inoederHelper(root, list);    return list;}
private void inoederHelper(TreeNode current, List list) {    if (current == null) {        return;    }    inoederHelper(current.left, list);    list.add(current.val);    inoederHelper(current.right, list);}```
### 思路分析1. **递归终止条件**:当前节点为null时返回2. **递归过程**:   - 先递归遍历左子树   - 访问当前节点(将值加入列表)   - 再递归遍历右子树3. **特点**:利用系统调用栈实现回溯,代码简洁易懂
### 时间复杂度- O(n),每个节点都会被访问一次
### 空间复杂度- 最坏情况下O(n)(树退化为链表时)- 平均情况下O(h),h为树的高度
## 三、迭代实现
### 代码实现```javapublic List<Integer> inorderTraversal2(TreeNode root) {    List<Integer> list = new ArrayList<>();    Stack<TreeNode> stack = new Stack<>();    TreeNode current = root;        while (current != null || !stack.isEmpty()) {        while (current != null) {            stack.push(current);            current = current.left;        }        current = stack.pop();        list.add(current.val);        current = current.right;    }    return list;}```
### 思路分析1. **使用栈模拟递归**:显式地使用栈来代替递归中的系统调用栈2. **算法步骤**:   - 从根节点开始,将所有左子节点入栈   - 弹出栈顶元素(最左节点)并访问   - 转向该节点的右子树,重复上述过程3. **循环条件**:当前节点不为空或栈不为空   - 当前节点不为空:说明还有左子树需要处理   - 栈不为空:说明还有节点需要访问
### 时间复杂度- O(n),每个节点都会被访问一次
### 空间复杂度- O(h),h为树的高度,栈的最大深度等于树的高度
## 四、两种实现方式对比
| 特性        | 递归实现               | 迭代实现               ||-------------|-----------------------|-----------------------|| 代码复杂度  | 简单                  | 较复杂                || 空间复杂度  | 隐式系统栈,可能溢出  | 显式栈,更可控        || 适用场景    | 树深度不大时          | 树深度较大时          || 可读性      | 高                    | 中等                  |
## 五、测试用例验证
测试用例构建的二叉树结构:```        1       / \      2   3     / \   \    4   5   6           /          7```
预期中序遍历结果:`[4, 2, 5, 1, 7, 6, 3]`
两种实现方式均输出正确结果,验证了代码的正确性。
## 六、总结
1. 递归实现简洁直观,适合理解中序遍历的基本原理2. 迭代实现效率更高,适合处理深度较大的树3. 两种实现方式的核心思想相同:左-根-右的访问顺序4. 在实际应用中,可以根据具体情况选择合适的方法:   - 面试中通常要求掌握两种实现   - 实际项目中,树不大时可用递归,树很深时建议用迭代
## 七、可能的改进方向
1. 可以添加Morris遍历的实现,实现O(1)空间复杂度的中序遍历2. 对于迭代实现,可以增加对栈溢出异常的处理3. 可以扩展为通用的二叉树遍历模板,只需调整访问顺序即可实现前序、中序、后序遍历
posted @ 2025-03-25 09:27  摆烂卧底  阅读(398)  评论(0)    收藏  举报