二叉树的迭代遍历 | LeetCode 144. 二叉树的前序遍历、LeetCode 94. 二叉树的中序遍历、LeetCode 145. 二叉树的后序遍历

二叉树的前序遍历(迭代法)

1、题目

题目链接: 144. 二叉树的前序遍历

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

示例 1:

复制代码
输入:root = [1,null,2,3]
输出:[1,2,3]

示例 2:

复制代码
输入:root = []
输出:[]

示例 3:

复制代码
输入:root = [1]
输出:[1]

示例 4:

复制代码
输入:root = [1,2]
输出:[1,2]

示例 5:

复制代码
输入:root = [1,null,2]
输出:[1,2]

提示:

  • 树中节点数目在范围 0, 100
  • -100 <= Node.val <= 100

2、思路

我们也可以用迭代的方式实现的递归函数,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同,具体可以参考下面的代码。

3、代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <stack>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> stk;
        vector<int> result;
        if (root == NULL) return result;
        stk.push(root);
        while (!stk.empty()) {
            // 取出栈顶节点
            TreeNode* node = stk.top();
            stk.pop();
            // 将节点值加入结果集
            result.push_back(node->val);
            // 如果右子节点不为空,则将右子节点入栈(空节点不入栈)
            if (node->right) stk.push(node->right);           
            // 如果左子节点不为空,则将左子节点入栈(空节点不入栈)
            if (node->left) stk.push(node->left);
        }
        return result;
    }
};

int main() {
    Solution s;
    TreeNode* root = new TreeNode(1, new TreeNode(2, new TreeNode(4), new TreeNode(5)), new TreeNode(3));
    vector<int> res = s.preorderTraversal(root);
    for (int i : res) {
        cout << i << " ";
    }
    cout << endl;
    return 0;
}

4、复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数。每一个节点恰好被遍历一次。
  • 空间复杂度:O(n),为迭代过程中显式栈的开销,平均情况下为 O(log⁡n),最坏情况下树呈现链状,为 O(n)。

二叉树的中序遍历(迭代法)

1、题目

题目链接: 94. 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回 它的 中序 遍历

示例 1:

复制代码
输入:root = [1,null,2,3]
输出:[1,3,2]

示例 2:

复制代码
输入:root = []
输出:[]

示例 3:

复制代码
输入:root = [1]
输出:[1]

提示:

  • 树中节点数目在范围 0, 100
  • -100 <= Node.val <= 100

2、思路

我们也可以用迭代的方式实现的递归函数,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同,具体可以参考下面的代码。

3、代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <stack>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> stk;
        TreeNode* cur = root;

        // 当当前节点不为空或者栈不为空时,继续循环
        while(cur != nullptr || !stk.empty()) {
            // 如果当前节点不为空
            if(cur != nullptr) {
                // 将当前节点入栈
                stk.push(cur);
                // 将当前节点指向左子节点
                cur = cur->left;
            } else {
                // 将栈顶节点出栈,并赋值给当前节点
                cur = stk.top();
                stk.pop();
                // 将当前节点的值添加到结果集中
                result.push_back(cur->val);
                // 将当前节点指向右子节点
                cur = cur->right;
            }
        }
        // 返回结果集
        return result;
    }
};


int main() {
    Solution s;
    TreeNode* root = new TreeNode(1, new TreeNode(2, new TreeNode(3), new TreeNode(4)), new TreeNode(5));
    vector<int> res = s.inorderTraversal(root);
    for (int i : res) {
        cout << i << " ";
    }
    cout << endl;
    return 0;
}

4、复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数。每一个节点恰好被遍历一次。
  • 空间复杂度:O(n),为迭代过程中显式栈的开销,平均情况下为 O(log⁡n),最坏情况下树呈现链状,为 O(n)。

二叉树的后序遍历(迭代法)

1、题目

题目链接: 145. 二叉树的后序遍历

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历

示例 1:

复制代码
输入:root = [1,null,2,3]
输出:[3,2,1]

示例 2:

复制代码
输入:root = []
输出:[]

示例 3:

复制代码
输入:root = [1]
输出:[1]

提示:

  • 树中节点的数目在范围 0, 100
  • -100 <= Node.val <= 100

2、思路

我们也可以用迭代的方式实现的递归函数,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同,具体可以参考下面的代码。

3、代码

cpp 复制代码
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>

using namespace std;

struct TreeNode {
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> stk;
        vector<int> result;
        if (root == NULL) return result;
        stk.push(root);
        while (!stk.empty()) {
            TreeNode* node = stk.top();
            stk.pop();
            result.push_back(node->val);
            // 后序遍历是先左后右最后根节点,所以这里先压入左子节点
            if (node->left) stk.push(node->left);
            // 然后压入右子节点
            if (node->right) stk.push(node->right);
        }
        // 后序遍历的结果是左右中,所以需要反转结果数组
        reverse(result.begin(), result.end());
        return result;
    }
};

int main() {
    Solution s;
    TreeNode* root = new TreeNode(1, new TreeNode(2, new TreeNode(4), new TreeNode(5)), new TreeNode(3, new TreeNode(6), new TreeNode(7)));
    vector<int> res = s.postorderTraversal(root);
    for (int i : res) {
        cout << i << " ";
    }
    cout << endl;
    return 0;
}

4、复杂度分析

  • 时间复杂度:O(n),其中 n 是二叉树的节点数。每一个节点恰好被遍历一次。
  • 空间复杂度:O(n),为迭代过程中显式栈的开销,平均情况下为 O(log⁡n),最坏情况下树呈现链状,为 O(n)。
相关推荐
zyplayer-doc5 小时前
VuePress类静态文档站和动态知识库怎么选:两种技术路线的适用场景
javascript·人工智能·后端·安全·智能手机
rannn_1116 小时前
【力扣hot100】链表专题|160、206、234、141、142
java·算法·leetcode·链表·面试·开发
数模竞赛Paid answer6 小时前
2026年华东杯数学建模B题医药物流安排问题解题全过程文档及程序
算法·数学建模·数据分析·华东杯
不会代码的小猴6 小时前
21. 泛型编程上
开发语言·c++·笔记·算法
营养充电站7 小时前
VS Code Git 工作树:解锁多分支并行开发的高效体验
leetcode·决策树·逻辑回归·散列表·模拟退火算法
青瓦梦滋7 小时前
传输层UDP/TCP协议
linux·网络·c++·网络协议·tcp/ip·udp
AI备案指南-满满7 小时前
大模型与算法备案全流程详解:从零到通过的完整指南
人工智能·算法·备案·大模型备案·算法备案
江畔柳前堤7 小时前
LLM 训练核心机制深度解析:Warmup、Cosine Decay 与 Perplexity 的完整知识体系
网络·人工智能·深度学习·算法·机器学习·语音识别
用户938515635077 小时前
从前后端分离到前端接口工程:React + MockJS + Vite 解析
前端·后端·全栈