代码随想录第八天|二叉树

目录

LeetCode 144. 二叉树的前序遍历

LeetCode 145. 二叉树的后序遍历

LeetCode 94.   二叉树的中序遍历

LeetCode 102. 107. 199. 637. 429. 515. 116. 117. 104. 111. 二叉树的层序遍历

总结


今天主要是了解了二叉树的主要遍历方式,广度和深度遍历方式。

LeetCode 144. 二叉树的前序遍历

LeetCode 145. 二叉树的后序遍历

LeetCode 94.   二叉树的中序遍历

题目链接:LeetCode 94. 二叉树的中序遍历LeetCode 145. 二叉树的后序遍历LeetCode 144. 二叉树的前序遍历

递归思想:首先需要确定递归函数的形参,第一个就是目前节点,其次需要一个能存储节点数值的数组;如果这个节点是空节点的话,就直接return掉;如果节点不为空的话,就要进行遍历了,前中后序的要求如下:

  • 前序遍历:先存储这个节点的值,再递归这个节点的左节点,最后是右节点;
  • 中序遍历:先递归这个节点的左节点,再存储这个节点的值,最后是右节点;
  • 后序遍历:先递归这个节点的左右皆,再递归右节点,最后村粗这个节点值。

代码如下:

    // 前序遍历
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) return;
        vec.push_back(cur->val);    // 中
        traversal(cur->left, vec);  // 左
        traversal(cur->right, vec); // 右
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }

    // 中序遍历
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) return;
        traversal(cur->left, vec);  // 左
        vec.push_back(cur->val);    // 中
        traversal(cur->right, vec); // 右
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }

    // 后序遍历
    void traversal(TreeNode* cur, vector<int>& vec) {
        if (cur == NULL) return;
        traversal(cur->left, vec);  // 左
        traversal(cur->right, vec); // 右
        vec.push_back(cur->val);    // 中
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        traversal(root, result);
        return result;
    }

迭代思想:前中后序的迭代方法基本上完全不一样,所以只能分别介绍了。

首先就是前序遍历了,前序遍历是中左右,每次都是先处理的中间节点,那么就将根节点先放入一个栈里面,然后右节点入栈,再左节点入栈。这样出栈的时候就是左节点再右节点了。

代码如下:

    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();                       // 中
            st.pop();
            result.push_back(node->val);
            if (node->right) st.push(node->right);           // 右(空节点不入栈)
            if (node->left) st.push(node->left);             // 左(空节点不入栈)
        }
        return result;
    }

后序遍历和前序遍历有丶像,所以先把后序遍历讲了。后序遍历是左右中,前序遍历是中左右,那么可以把前序遍历的顺序稍微改那么一下下,变成中右左,到最后的时候把给出来的数组反转一下不就是左右中了吗。

代码如下:

    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            result.push_back(node->val);
            if (node->left) st.push(node->left); // 相对于前序遍历,这更改一下入栈顺序 (空节点不入栈)
            if (node->right) st.push(node->right); // 空节点不入栈
        }
        reverse(result.begin(), result.end()); // 将结果反转之后就是左右中的顺序了
        return result;
    }

最后就是中序遍历了,中序遍历是左中右。因为根节点在中间,但是最先访问的节点要根据根节点一步一步向下访问,直到达到数最左边的最底部,再开始处理节点,处理的顺序与访问顺序不一致。

在使用迭代法写中序遍历,就需要借用指针的遍历来帮助访问节点,栈则用来处理节点上的元素。

代码如下:

    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        TreeNode* cur = root;
        while (cur != NULL || !st.empty()) {
            if (cur != NULL) { // 指针来访问节点,访问到最底层
                st.push(cur); // 将访问的节点放进栈
                cur = cur->left;                // 左
            } else {
                cur = st.top(); // 从栈里弹出的数据,就是要处理的数据(放进result数组里的数据)
                st.pop();
                result.push_back(cur->val);     // 中
                cur = cur->right;               // 右
            }
        }
        return result;
    }

LeetCode 102. 107. 199. 637. 429. 515. 116. 117. 104. 111. 二叉树的层序遍历

题目链接:LeetCode 102. 二叉树的层序遍历LeetCode 107. 二叉树的层序遍历 IILeetCode 199. 二叉树的右视图LeetCode 637. 二叉树的层平均值LeetCode 429. N叉树的层序遍历LeetCode 515. 在每个树行中找最大值LeetCode 116. 填充每个节点的下一个右侧节点指针LeetCode 117. 填充每个节点的下一个右侧节点指针 II
LeetCode 104. 二叉树的最大深度LeetCode 111. 二叉树的最小深度

思想:这十个题都可以采用层序遍历的方式来解决,所以只要掌握了层序遍历,这十个题根本不在话下。层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。这种遍历的方式和我们之前讲过的都不太一样。需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。而这种层序遍历方式就是图论中的广度优先遍历,只不过我们应用在二叉树上。

代码如下:

    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            // 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                vec.push_back(node->val);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(vec);
        }
        return result;
    }

总结

遍历是数据结构的基本,掌握遍历才能完成后序操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值