【Leetcode】 94. 二叉树的中序遍历

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


输入root = [1,null,2,3]
输出[1,3,2]

示例 2

输入root = []
输出[]
示例 3

输入root = [1]
输出[1]

提示

cpp 复制代码
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100

进阶 : 递归算法 很简单,你可以通过迭代算法完成吗?


AC:

cpp 复制代码
/*
 * @lc app=leetcode.cn id=94 lang=cpp
 *
 * [94] 二叉树的中序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * 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> res;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while(cur || !st.empty()) {
            if(cur) {
                st.push(cur);
                cur = cur->left;
            }
            else {
                cur = st.top();
                st.pop();
                res.push_back(cur->val);
                cur = cur->right;
            }
        }
        return res;
    }
};
// @lc code=end

着重谈一下 Morris 遍历
AC

cpp 复制代码
/*
 * @lc app=leetcode.cn id=94 lang=cpp
 *
 * [94] 二叉树的中序遍历
 */

// @lc code=start
/**
 * Definition for a binary tree node.
 * 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) {}
 * };
 */
/*
    Morris 遍历中,需要利用前驱节点指向当前节点的方式来遍历二叉树,
    算法的核心思想是将二叉树中每个节点的前驱节点的右孩子指向该节点,
    这样在遍历完当前节点的左子树后,
    可以通过前驱节点的右孩子指针找到该节点,
    并且不需要再次遍历该节点的左子树。遍历完成后,
    需要将前驱节点的右孩子指针重置为空。
*/
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
    // 定义结果数组和前驱节点指针
    vector<int> res;
    TreeNode *predecessor = nullptr;
    // 循环迭代直到遍历完整个二叉树
    while(root)
    {
        // 如果当前节点有左子节点,需要找到其左子树的最右侧节点作为前驱节点
        if(root->left)
        {
            // 找到前驱节点
            predecessor = root->left;
            while(predecessor->right && predecessor->right != root)
                predecessor = predecessor->right;
            // 如果前驱节点的右孩子为空,则将前驱节点的右孩子指向当前节点,然后遍历左子树
            if(predecessor->right == nullptr)
            {
                predecessor->right = root;
                root = root->left;
            }
            // 如果前驱节点的右孩子指向当前节点,说明左子树已经遍历完成,将前驱节点的右孩子置为空,并将当前节点加入结果数组,然后遍历右子树
            else{
                res.push_back(root->val);
                predecessor->right = nullptr;
                root = root->right;
            }
        }
        // 如果当前节点没有左子节点,则将当前节点加入结果数组,然后遍历右子树
        else{
            res.push_back(root->val);
            root = root->right;
        }
    }
    // 返回结果数组
    return res;
    }
};
// @lc code=end

Morris遍历是一种使用线索二叉树进行遍历的算法,它的空间复杂度O(1)。以下是C++代码实现:

前序遍历

cpp 复制代码
void morrisPreorderTraversal(TreeNode* root) {
    if (!root) return;
    TreeNode* cur = root, *predecessor = nullptr;
    while (cur) {
        if (!cur->left) {
            cout << cur->val << " ";
            cur = cur->right;
        }
        else {
            predecessor = cur->left;
            while (predecessor->right && predecessor->right != cur) {
                predecessor = predecessor->right;
            }
            if (!predecessor->right) {
                cout << cur->val << " ";
                predecessor->right = cur;
                cur = cur->left;
            }
            else {
                predecessor->right = nullptr;
                cur = cur->right;
            }
        }
    }
}

中序遍历:

cpp 复制代码
void morrisInorderTraversal(TreeNode* root) {
    if (!root) return;
    TreeNode* cur = root, *predecessor = nullptr;
    while (cur) {
        if (!cur->left) {
            cout << cur->val << " ";
            cur = cur->right;
        }
        else {
            predecessor = cur->left;
            while (predecessor->right && predecessor->right != cur) {
                predecessor = predecessor->right;
            }
            if (!predecessor->right) {
                predecessor->right = cur;
                cur = cur->left;
            }
            else {
                predecessor->right = nullptr;
                cout << cur->val << " ";
                cur = cur->right;
            }
        }
    }
}

后序遍历:

cpp 复制代码
vector<int> morrisPostorderTraversal(TreeNode* root) {
    if (!root) return {};
    vector<int> res;
    TreeNode* cur = root, *predecessor = nullptr;
    while (cur) {
        if (!cur->right) {
            res.push_back(cur->val);
            cur = cur->left;
        }
        else {
            predecessor = cur->right;
            while (predecessor->left && predecessor->left != cur) {
                predecessor = predecessor->left;
            }
            if (!predecessor->left) {
                res.push_back(cur->val);
                predecessor->left = cur;
                cur = cur->right;
            }
            else {
                predecessor->left = nullptr;
                cur = cur->left;
            }
        }
    }
    reverse(res.begin(), res.end());
    return res;
}
相关推荐
yaoh.wang4 小时前
力扣(LeetCode) 13: 罗马数字转整数 - 解法思路
python·程序人生·算法·leetcode·面试·职场和发展·跳槽
T1ssy4 小时前
布隆过滤器:用概率换空间的奇妙数据结构
算法·哈希算法
hetao17338374 小时前
2025-12-12~14 hetao1733837的刷题笔记
数据结构·c++·笔记·算法
鲨莎分不晴5 小时前
强化学习第五课 —— A2C & A3C:并行化是如何杀死经验回放
网络·算法·机器学习
搞科研的小刘选手6 小时前
【ISSN/ISBN双刊号】第三届电力电子与人工智能国际学术会议(PEAI 2026)
图像处理·人工智能·算法·电力电子·学术会议
拉姆哥的小屋6 小时前
从混沌到秩序:条件扩散模型在图像转换中的哲学与技术革命
人工智能·算法·机器学习
Sammyyyyy6 小时前
DeepSeek v3.2 正式发布,对标 GPT-5
开发语言·人工智能·gpt·算法·servbay
sin_hielo7 小时前
leetcode 2110
数据结构·算法·leetcode
Jay20021117 小时前
【机器学习】33 强化学习 - 连续状态空间(DQN算法)
人工智能·算法·机器学习
铭哥的编程日记7 小时前
后端面试通关笔记:从真题到思路(五)
面试·职场和发展