二叉树的中序遍历(非递归实现)

中序遍历的顺序是:左子树 → 根节点 → 右子树。递归实现很直观,但迭代版本能帮我们更好地理解栈的工作原理,也能避免递归深度过大带来的问题。这里给出一种用栈模拟的迭代解法。

思路

中序遍历的非递归核心思想是:沿着左子树一路向下,将沿途节点压栈,直到左子树为空;然后弹出栈顶节点(即最近一个左子树为空的节点)并访问它,接着处理它的右子树

这个过程模拟了递归函数调用的行为:递归左子树时,将当前节点状态保存;左子树返回后,访问当前节点;然后递归右子树。

代码

cpp

复制代码
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        TreeNode* cur = root;

        while (cur != nullptr || !st.empty()) {
            // 一直向左走,将节点压栈
            while (cur != nullptr) {
                st.push(cur);
                cur = cur->left;
            }
            // 当前节点为空,说明左子树走到头了,弹出栈顶并访问
            TreeNode* top = st.top();
            st.pop();
            result.push_back(top->val);
            // 转向右子树
            cur = top->right;
        }
        return result;
    }
};

代码解释

  • cur 指针指向当前要处理的节点,初始为根节点。

  • 外层 while 循环保证当还有节点未处理时继续执行。条件 cur != nullptr || !st.empty() 涵盖了刚开始树非空以及栈中还有节点的情况。

  • 内层 while 循环:只要当前节点不为空,就一直往左走,并将沿途节点压栈。这是为了找到最左边的节点,同时把路径上的根节点保存下来,以便后续处理右子树。

  • 当内层循环退出,说明 cur 已经为空,此时栈顶节点就是当前需要访问的节点(它的左子树已经处理完毕)。弹出栈顶,将其值加入结果数组。

  • 然后 cur 指向该节点的右子树,开始处理右子树(进入下一轮外层循环,对右子树重复同样的过程)。

复杂度分析

  • 时间复杂度:O(n),每个节点恰好被压栈一次、弹栈一次,访问一次。

  • 空间复杂度:O(h),h 为树的高度。栈中最多同时存放一条从根到当前节点的路径上的节点。最坏情况(树退化为链表)下空间复杂度 O(n),平均情况 O(logn)。

为什么用迭代而不是递归?

递归写法更简洁,但迭代有两个好处:

  1. 避免递归调用栈溢出(当树深度很大时,系统栈可能不够用)。

  2. 显式地使用栈,可以帮助理解深度优先遍历的本质,为后续更复杂的非递归遍历(如后序、Morris 遍历)打下基础。

注意事项

  • 空树处理:如果 root 为空,外层循环条件不满足,直接返回空数组。

  • 循环条件中 cur 和栈的状态需要配合理解:cur 可能为空但栈不为空,表示还有右子树要处理;两者都为空时遍历结束。

  • 代码中的 cur 在访问完节点后直接指向右孩子,即使右孩子为空,下一轮内层循环也不会执行,直接弹出下一个节点。

总结

中序遍历的迭代实现是二叉树遍历的基础模板,理解了这个过程,后续的前序和后序非递归也能触类旁通。关键点在于利用栈保存待处理的节点,并控制访问时机(出栈时访问)。掌握了这个,很多树的题目就能用迭代方式解决了。

相关推荐
别动我齐刘海20 小时前
机器人运动控制学习2——基础进阶
c++·人工智能·神经网络·学习·目标检测·机器学习·机器人
小庞在加油20 小时前
WinDbg实战:QT/跨平台项目死锁与无响应问题排查指南
开发语言·qt·windbg·工具
IT技术分享社区20 小时前
Windows桌面时钟推荐:始终置顶、无级缩放、支持全屏游戏显示时间
windows·微软技术·电脑技巧·桌面美化·电脑干货
Vae_Mars20 小时前
C#中的delegate委托
开发语言·c#
傻啦嘿哟20 小时前
英雄联盟皮肤爬虫:爬取全皮肤价格与特效,做比价工具
java·c++·爬虫
一直走下去-明21 小时前
简单的http抓包解包完整代码
开发语言·python
caimouse21 小时前
ReactOS 图形系统分析(51):元文件子系统 — metafile.c
c语言·开发语言
码匠许师傅21 小时前
【C++ 面试真题】24. 聊聊 C++ 的时间日期处理
java·c++·面试
wenyq721 小时前
LeetCode 2460. Apply Operations to an Array
算法·leetcode
闻道且行之21 小时前
图片处理助手|泊松融合原理 + C++ 工程实现,seamlessClone 三模式一次讲透
数据库·c++·人工智能·opencv