【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;
}
相关推荐
hsling松子4 小时前
使用PaddleHub智能生成,献上浓情国庆福
人工智能·算法·机器学习·语言模型·paddlepaddle
dengqingrui1234 小时前
【树形DP】AT_dp_p Independent Set 题解
c++·学习·算法·深度优先·图论·dp
C++忠实粉丝4 小时前
前缀和(8)_矩阵区域和
数据结构·c++·线性代数·算法·矩阵
ZZZ_O^O5 小时前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
CV-King5 小时前
opencv实战项目(三十):使用傅里叶变换进行图像边缘检测
人工智能·opencv·算法·计算机视觉
代码雕刻家6 小时前
数据结构-3.9.栈在递归中的应用
c语言·数据结构·算法
雨中rain6 小时前
算法 | 位运算(哈希思想)
算法
Kalika0-07 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
sp_fyf_20248 小时前
计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-02
人工智能·神经网络·算法·计算机视觉·语言模型·自然语言处理·数据挖掘
我是哈哈hh9 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝