94. 二叉树的中序遍历详解:迭代法核心逻辑与出入栈模拟

中序遍历是二叉树遍历中最经典的算法之一,其核心顺序是 “左子树 → 根节点 → 右子树”。递归实现非常简单,但理解迭代法的实现却需要掌握栈的操作细节。本文将通过代码逐行解析,结合出入栈的模拟,彻底讲透迭代法的核心逻辑。


题目描述

给定一个二叉树的根节点 root,返回它的 中序 遍历结果。例如,输入 root = [1,null,2,3],输出 [1,3,2]


核心难点分析

1. 出入栈顺序

  • 何时入栈? 当当前节点存在左子树时,不断向左深入,将所有左节点入栈。
  • 何时出栈? 当左子树遍历到底(tempnull)时,弹出栈顶元素,处理该节点,并转向其右子树。

2. 循环的逻辑

  • 循环条件temp != null || !stack.isEmpty()
    • temp != null:表示仍有左子树需要探索;
    • !stack.isEmpty():表示需要回溯到之前的节点处理右子树。

3. 规律总结

  • “有左入左,无左入右,自底向上”
    • 有左子树时,持续向左入栈;
    • 无左子树时,弹出栈顶节点,记录值,并转向右子树;
    • 最终遍历顺序是从最左节点开始,自底向上处理。

解题思路分步解析

步骤 1:初始化栈和结果列表

List<Integer> res = new ArrayList<>();  // 存储遍历结果
Stack<TreeNode> stack = new Stack<>();  // 模拟递归的栈
TreeNode temp = root;                   // 当前处理节点

步骤 2:循环处理节点

while (temp != null || !stack.isEmpty()) {
    // 1. 有左子树:持续向左深入,节点入栈
    if (temp != null) {
        stack.push(temp);
        temp = temp.left;
    }
    // 2. 无左子树:弹出栈顶节点,记录值,转向右子树
    else {
        temp = stack.pop();
        res.add(temp.val);
        temp = temp.right;
    }
}

出入栈模拟示例

以二叉树 [1,2,3,4,5] 为例,结构如下:

    1
   / \
  2   3
 / \
4   5

中序遍历结果应为 [4,2,5,1,3]。以下是栈的变化过程:

当前 temp栈内容(底→顶)操作结果 res
1[]压入 1,转向左子 2[]
2[1]压入 2,转向左子 4[]
4[1,2]压入 4,转向左子 null[]
null[1,2,4]弹出 4,记录 4,转向右子 null[4]
null[1,2]弹出 2,记录 2,转向右子 5[4,2]
5[1]压入 5,转向左子 null[4,2]
null[1,5]弹出 5,记录 5,转向右子 null[4,2,5]
null[1]弹出 1,记录 1,转向右子 3[4,2,5,1]
3[]压入 3,转向左子 null[4,2,5,1]
null[3]弹出 3,记录 3,转向右子 null[4,2,5,1,3]

关键知识点总结

1. 为什么用栈?

  • 模拟递归调用栈:递归的本质是系统维护的栈,迭代法通过显式栈手动模拟这一过程。
  • 避免栈溢出:当树深度较大时,递归可能引发栈溢出,迭代法更安全。

2. 循环条件的意义

  • temp != null:表示当前仍有未探索的左子树。
  • !stack.isEmpty():表示需要回溯到之前的节点处理右子树。

3. 时间复杂度与空间复杂度

  • 时间复杂度:O(n),每个节点恰好被访问两次(入栈和出栈)。
  • 空间复杂度:O(n),最坏情况下栈存储所有节点。

完整代码

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        TreeNode temp = root;
        while (temp != null || !stack.isEmpty()) {          
            if (temp != null) {
                stack.push(temp);
                temp = temp.left;
            } else {
                temp = stack.pop();
                res.add(temp.val);
                temp = temp.right;
            }
        }
        return res;
    }
}

总结

中序遍历的迭代法核心在于 “左-根-右” 的顺序控制。通过栈的压入和弹出操作,可以精确模拟递归的调用过程。关键在于:

  1. 向左深入到底,将所有左节点入栈;
  2. 回溯处理右子树,利用栈实现自底向上的遍历。
    掌握这一逻辑后,可以轻松应对二叉树相关的其他迭代遍历问题(如前序、后序)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值