Lishengxie logo Lishengxie

Always on the way

  • 文章
  • 关于我
  • 归档
  • 联系
  1. 首页
  2. 文章
  3. LeetCode刷题-二叉树遍历迭代法

LeetCode刷题-二叉树遍历迭代法

2023-10-17 算法学习 Lishengxie

LeetCode题目链接

二叉树的前序遍历:https://leetcode.cn/problems/binary-tree-preorder-traversal/ 二叉树的中序遍历:https://leetcode.cn/problems/binary-tree-inorder-traversal/ 二叉树的后序遍历:https://leetcode.cn/problems/binary-tree-postorder-traversal/

二叉树的遍历方法有两种,分别是递归法和迭代法;实际使用中由于系统调用栈有限制,使用递归法可能会导致栈溢出,这里记录三种遍历的迭代做法。最后,介绍二叉树层序遍历的两种方法。

迭代遍历法借助辅助栈实现,下面是二叉树节点的定义,使用链表实现。

 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) {
        vector<int> res;
        stack<TreeNode*> st;
        if (root == NULL) {
            return res;
        }

        st.push(root);
        while (!st.empty()) {
            TreeNode *cur = st.top();
            st.pop();
            res.push_back(cur->val);
            if (cur->right) st.push(cur->right);
            if (cur->left) st.push(cur->left);
        }

        return res;
    }
};

中序遍历

中序遍历处理顺序为左中右,先访问二叉树顶部的节点,随后逐层向下访问直到树最左侧的节点,再开始处理节点,这导致处理节点的顺序和访问节点的顺序不一致。中序遍历的迭代法如下所示:

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        if (root == NULL) {
            return res;
        }
        TreeNode *cur = root;
        while (cur!=NULL || !st.empty()) {
            if (cur != NULL) {
                if (cur) st.push(cur);
                cur = cur->left;
            } else {
                cur = st.top();
                st.pop();
                res.push_back(cur->val);
                cur = cur->right;
            }
        }
        return res;
    }
};

后序遍历

先序遍历是中左右,后续遍历是左右中,那么只需要调整一下先序遍历的代码顺序,就变成中右左的遍历顺序,然后在反转result数组,输出的结果顺序就是左右中了。后序遍历的代码如下所示:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        if (root == NULL) {
            return res;
        }
        st.push(root);
        while (!st.empty()) {
            TreeNode *cur = st.top();
            st.pop();
            if (cur->left) st.push(cur->left);
            if (cur->right) st.push(cur->right);
            res.push_back(cur->val);
        }
        reverse(res.begin(), res.end());
        return res;   
    }
};

统一的迭代遍历法

参考https://programmercarl.com/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E7%BB%9F%E4%B8%80%E8%BF%AD%E4%BB%A3%E6%B3%95.html 每次在待处理节点入栈后,加入一个NULL节点作为标记,之后在遇到NULL节点时处理栈中的下一个节点。需要注意的是,这种方法效率不高,节点可能会多次入栈。

层序遍历

// 迭代遍历,BFS基于队列
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode*> q;
        if (root == NULL)  {
            return res;
        }

        q.push(root);
        while (!q.empty()) {
            int size =q.size();
            vector<int> layer;
            for (int i = 0; i < size; ++i) {
                TreeNode *cur = q.front();
                q.pop();
                layer.push_back(cur->val);
                if (cur->left) q.push(cur->left);
                if (cur->right) q.push(cur->right);
            }
            res.push_back(layer);
        }
        return res;
    }
};

// 递归,DFS
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode*> q;
        if (root == NULL)  {
            return res;
        }

        order(0, root, res);
        return res;
    }

    // DFS, 递归
    void order(int depth, TreeNode *cur, vector<vector<int>> &res) {
        if (cur == NULL) return;
        if (res.size() == depth) res.push_back(vector<int>());
        res[depth].push_back(cur->val);
        order(depth + 1, cur->left, res);
        order(depth + 1, cur->right, res);
    }
};
算法 LeetCode 二叉树

本文目录

  • LeetCode题目链接
  • 前序遍历
  • 中序遍历
  • 后序遍历
  • 统一的迭代遍历法
  • 层序遍历

精选文章

  • 分布式ID生成方案全解析:从数据库到雪花算法
  • Redis ziplist、quicklist 和 listpack
  • 多目标优化问题及两种常用解法

按主题探索

  • Redis 数据结构
    从存储布局理解实现
  • Linux 与部署
    服务器、证书与建站实践
  • 算法与深度学习
    解题方法、优化与公式推导
  • SNN / NoC 论文
    互连网络与映射算法

名言警句

学而时习之,不亦说乎?《论语·学而》学而不思则罔,思而不学则殆。《论语·为政》知之为知之,不知为不知,是知也。《论语·为政》三人行,必有我师焉。《论语·述而》工欲善其事,必先利其器。《论语·卫灵公》不积跬步,无以至千里。《荀子·劝学》千里之行,始于足下。《老子·第六十四章》纸上得来终觉浅,绝知此事要躬行。陆游《冬夜读书示子聿》
学而时习之,不亦说乎?
《论语·学而》 一言
← LeetCode刷题 - 滑动窗口最大值 算法学习-差分数组 →

相关文章

  • 算法学习-差分数组 Dec 23, 2023
  • LeetCode刷题 - 滑动窗口最大值 Oct 17, 2023
  • LeetCode刷题 - KMP算法 Feb 4, 2024
  • 多目标优化问题及两种常用解法 Apr 30, 2023
皖ICP备2023003716号-1 | 公安备案皖公网安备34012202341113 | 违法和不良信息举报邮箱:1141751053@qq.com
Powered by Hugo & Explore Theme & Theme by SimonAKing.