【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;
}
相关推荐
凌肖战2 小时前
力扣网编程55题:跳跃游戏之逆向思维
算法·leetcode
黑听人2 小时前
【力扣 简单 C】70. 爬楼梯
c语言·leetcode
88号技师3 小时前
2025年6月一区-田忌赛马优化算法Tianji’s horse racing optimization-附Matlab免费代码
开发语言·算法·matlab·优化算法
ゞ 正在缓冲99%…3 小时前
leetcode918.环形子数组的最大和
数据结构·算法·leetcode·动态规划
Kaltistss4 小时前
98.验证二叉搜索树
算法·leetcode·职场和发展
知己如祭4 小时前
图论基础(DFS、BFS、拓扑排序)
算法
mit6.8244 小时前
[Cyclone] 哈希算法 | SIMD优化哈希计算 | 大数运算 (Int类)
算法·哈希算法
c++bug4 小时前
动态规划VS记忆化搜索(2)
算法·动态规划
哪 吒4 小时前
2025B卷 - 华为OD机试七日集训第5期 - 按算法分类,由易到难,循序渐进,玩转OD(Python/JS/C/C++)
python·算法·华为od·华为od机试·2025b卷
军训猫猫头5 小时前
1.如何对多个控件进行高效的绑定 C#例子 WPF例子
开发语言·算法·c#·.net