代码随想录打卡第十三天

代码随想录--二叉树部分

day13 二叉树第一天


文章目录


二叉树基础知识

代码随想录知识链接:代码随想录

几个核心概念
满二叉树 :结点的度只有0和2,且度为0的节点在同一层
完全二叉树 :除了最后一层,其他层都满节点,最后一层的节点从左往右排
二叉搜索树 :带值的二叉树,左节点<根节点<右节点
平衡二叉树:空树或左右子树高度差不大于1

遍历方法:

今天的题目都是遍历,在题目中介绍

一、力扣144--二叉树的前序遍历(递归)

代码随想录知识链接:代码随想录

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

前序遍历意思就是根节点->左节点->右节点这种顺序遍历下去,先用递归方法

定义一个子函数,接受一个根节点,如果根节点为null就return,否则先递归其左节点,再递归其右节点

代码如下:

cpp 复制代码
class Solution {
public:
    void trans(TreeNode* curr, vector<int> & result)
    {
        if(curr == nullptr) return;
        result.push_back(curr->val);
        trans(curr->left, result);
        trans(curr->right, result);
    }
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        trans(root, result);
        return result;
    }
};

二、力扣145--二叉树的后序遍历(递归)

代码随想录知识链接:代码随想录

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历 。

后序遍历就是从子节点先遍历,左节点->右节点->根节点,调换一下子函数的顺序就行

代码如下:

cpp 复制代码
class Solution {
public:
    void trans(TreeNode* curr, vector<int> & result)
    {
        if(curr == nullptr) return;
        trans(curr->left, result);
        trans(curr->right, result);     
        result.push_back(curr->val);   
    }
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        trans(root, result);
        return result;
    }
};

三、力扣94--二叉树的中序遍历(递归)

代码随想录知识链接:代码随想录

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

中序的顺序是左节点->根节点->右节点

代码如下:

cpp 复制代码
class Solution {
public:
    void trans(TreeNode* curr, vector<int> & result)
    {
        if(curr == nullptr) return;
        trans(curr->left, result);
        result.push_back(curr->val);
        trans(curr->right, result);     
    }
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        trans(root, result);
        return result;
    }
};

四、力扣144--二叉树的前序遍历(迭代)

代码随想录知识链接:代码随想录

这次用迭代方法来遍历。递归的实现本身是每次递归调用都把函数压入调用栈中,等递归结束时,就从栈顶弹出上次递归的参数,迭代法也就是模拟这个过程。

前序是中左右,但是因为栈是先入后出,所以实际上压栈的顺序应该是右左中

代码如下:

cpp 复制代码
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if(root == nullptr) return result;
        st.push(root);
        while(!st.empty())
        {
            TreeNode * curr = st.top();
            result.push_back(curr->val);
            st.pop();
            if(curr->right)st.push(curr->right);
            if(curr->left)st.push(curr->left);
        }
        return result;
    }
};

五、力扣145--二叉树的后序遍历(迭代)

代码随想录知识链接:代码随想录

同样的,用遍历+栈模拟递归过程,先序是中左右,后序是左右中,也就是中右左的逆序,而中右左是很好调整的

代码如下:

cpp 复制代码
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if(root == nullptr) return result;
        st.push(root);
        while(!st.empty())
        {
            TreeNode * curr = st.top();
            result.push_back(curr->val);
            st.pop();
            if(curr->left)st.push(curr->left);
            if(curr->right)st.push(curr->right); // switch order
        }
        reverse(result.begin(), result.end()); // reverse the result
        return result;
    }
};

六、力扣94--二叉树的中序遍历(迭代)

代码随想录知识链接:代码随想录

中序遍历不管怎么调整,都没法把根节点放在第一位处理,它只能在中间,所以代码没法像前后序那么简单

所以这里栈就可以用来存指针,遍历到底部后,再出栈处理数字

代码如下:

cpp 复制代码
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode *> st;
        TreeNode * curr = root;
        while(curr != nullptr || !st.empty())
        {
            if(curr != nullptr)
            {
                st.push(curr);
                curr = curr->left;
            }
            else
            {
                curr = st.top();
                st.pop();
                result.push_back(curr->val);
                curr = curr->right;
            }
        }
        return result;
    }
};

七、力扣144--二叉树的前序遍历(统一迭代)

代码随想录知识链接:代码随想录

迭代法明显没有递归法那样漂亮,无法做到三种顺序改一点就能用,所以对迭代法改进,使其更漂亮更易用

其实相当于都写成中序遍历的样子,但是在遍历过未处理的节点入栈后,增加一个NULL指针也入栈,来表示该节点可以输出了

这样不同的遍历顺序只需要改入栈顺序就行,这样就和递归法一样了

代码如下:

cpp 复制代码
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if(root != nullptr) st.push(root);
        while(!st.empty())
        {
            TreeNode * curr = st.top();
            if(curr != nullptr)
            {
                st.pop();
                if(curr->right != nullptr) st.push(curr->right);
                if(curr->left != nullptr) st.push(curr->left);
                st.push(curr);
                st.push(nullptr);
            }
            else
            {
                st.pop();
                curr = st.top();
                st.pop();
                result.push_back(curr->val);                
            }
        }
        return result;
    }
};

八、力扣145--二叉树的后序遍历(统一迭代)

代码随想录知识链接:代码随想录

前序是中左右,入栈顺序是右左中,那么后序是左右中,则入栈顺序是中右左

cpp 复制代码
class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();
                st.push(node);                          
                st.push(NULL);
                if (node->right) st.push(node->right);  
                if (node->left) st.push(node->left);    

            } else {
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
};

九、力扣94--二叉树的中序遍历(统一迭代)

代码随想录知识链接:代码随想录

中序输出是左中右,那入栈顺序就是右中左

代码如下:

cpp 复制代码
class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> result;
        stack<TreeNode*> st;
        if (root != NULL) st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            if (node != NULL) {
                st.pop();

                if (node->right) st.push(node->right);  
                st.push(node);                          
                st.push(NULL);
                if (node->left) st.push(node->left);    

            } else {
                st.pop();
                node = st.top();
                st.pop();
                result.push_back(node->val);
            }
        }
        return result;
    }
};

十、力扣102--二叉树的层序遍历

代码随想录知识链接:代码随想录

前中后序遍历都是深度优先遍历,层序遍历就是广度优先了

用队列实现,每次将出队元素的子节点入队,直到队空即可

代码如下:

cpp 复制代码
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        queue<TreeNode *> que;
        if(root != nullptr) que.push(root);
        {
            while(!que.empty())
            {
                vector<int> temp;
                int length = que.size();
                for(int i = 0;i < length; i++) // Use all nodes in this while loop
                {
                    TreeNode * curr = que.front();
                    que.pop();
                    if(curr->left != nullptr) que.push(curr->left);
                    if(curr->right != nullptr) que.push(curr->right);
                    temp.push_back(curr->val);
                }
                result.push_back(temp);
            }
        }
        return result;
    }
};

不同于深度优先的是,在while里面处理节点时,需要把该次while循环的元素都遍历其子节点,不然又成深度优先了

相关推荐
湫兮之风17 分钟前
C++:.front()函数作用
开发语言·c++
小老鼠不吃猫18 分钟前
力学笃行(四)Qt 线程与信号槽
c++·qt·信息可视化
小羊子说18 分钟前
Android 开发中 C++ 和Java 日志调试
android·java·c++
TechQuester23 分钟前
解决GPT-4o耗电难题!DeepMind新算法训练效率提升13倍,能耗降低10倍!
java·c++·人工智能·python·算法·chatgpt
XSTIT32 分钟前
数据结构--二叉树相关题2(OJ)
数据结构·算法
续亮~38 分钟前
6、Redis系统-数据结构-06-跳表
java·数据结构·数据库·redis·后端·缓存
观鉴词recommend39 分钟前
【c++刷题笔记-动态规划】day32: 509. 斐波那契数 、 70. 爬楼梯 、 746. 使用最小花费爬楼梯
c++·笔记·算法·leetcode·动态规划
DieSnowK39 分钟前
[C++][ProtoBuf][初识ProtoBuf]详细讲解
开发语言·c++·google·协议·序列化·反序列化·protobuf
不决问春风1 小时前
102.二叉树的层序遍历——二叉树专题复习
java·算法·leetcode
酷酷学!!!1 小时前
C++第一弹 -- C++基础语法上(命名空间 输入输出 缺省参数 函数重载 引用)
开发语言·c++·学习方法·visual studio