二叉树的遍历

目录

二叉树的遍历方式

深度遍历DFS

题目链接:144. 二叉树的前序遍历 - 力扣(LeetCode)

题目链接:94. 二叉树的中序遍历 - 力扣(LeetCode)

题目链接:145. 二叉树的后序遍历 - 力扣(LeetCode)

题目链接:589. N 叉树的前序遍历 - 力扣(LeetCode)

题目链接:590. N 叉树的后序遍历 - 力扣(LeetCode)

广度遍历BFS

题目链接:102. 二叉树的层序遍历 - 力扣(LeetCode)

题目链接:107. 二叉树的层序遍历 II - 力扣(LeetCode)

题目链接:199. 二叉树的右视图 - 力扣(LeetCode)

 题目链接:637. 二叉树的层平均值 题解 - 力扣(LeetCode)

题目链接:429. N 叉树的层序遍历 - 力扣(LeetCode)

题目链接:515. 在每个树行中找最大值 - 力扣(LeetCode)

题目链接:116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)

题目链接:117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)

题目链接:104. 二叉树的最大深度 - 力扣(LeetCode)

题目链接:111. 二叉树的最小深度 - 力扣(LeetCode)


二叉树的遍历方式

1.深度优先遍历

  • 前序遍历:根左右
  • 中序遍历:左根右
  • 后序遍历:左右根

2.广度优先遍历

  • 层次遍历

题目链接:144. 二叉树的前序遍历 - 力扣(LeetCode)

class Solution{//前序遍历递归
public:
    vector<int> preorderTraversal(TreeNode *root){
        vector<int> res;
        travel(root,res);
        return res;
    }
private:
    void travel(TreeNode *cur, vector<int> &res){
        if(cur==NULL)   return;
        res.push_back(cur->val);//根
        travel(cur->left,res);//左
        travel(cur->right,res);//右
    }
};

class Solution {//前序遍历迭代
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        if(root==NULL)  return res;
        TreeNode *cur=root;
        st.push(root);//将根结点压入栈中                            
        while(!st.empty()){//当栈不为空时,表明其中还有结点未遍历
            //首先将每棵子树的根节点pop并压入res数组
            TreeNode *node=st.top();
            st.pop();
            res.push_back(node->val);                //根
            //先右后左,这样pop出来就是先左后右
            //如果右子树不为空,将右子树根节点压入栈中
            if(node->right) st.push(node->right);    //右
            //如果左子树不为空,将左子树根节点压入栈中
            if(node->left)  st.push(node->left);    //左
        }
        return res;
    }
};

class Solution {//前序遍历统一迭代
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root==NULL)  return res;
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty()){
            //将栈顶结点取出
            TreeNode *cur=st.top();st.pop();
            if(cur!=NULL){//如果栈顶结点不为空
                //重新按照倒序向栈中压入该结点及其孩子
                if(cur->right)  st.push(cur->right);//右
                if(cur->left)   st.push(cur->left); //左
                st.push(cur);                       //根
                
                st.push(NULL);//NULL用来标记根结点所在位置
            }
            else{//如果栈顶结点为空,则要处理根节点,即其上一个结点
                cur=st.top();st.pop();
                res.push_back(cur->val);
            }
        }
        return res;
    }
};

题目链接:94. 二叉树的中序遍历 - 力扣(LeetCode)

class Solution {//中序遍历递归
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root==NULL)  return res;
        traversal(root,res);
        return res;
    }
private:
    void traversal(TreeNode *cur,vector<int> &res){
        if(cur==NULL)   return ;
        traversal(cur->left,res);   //左
        res.push_back(cur->val);    //根
        traversal(cur->right,res);  //右
    }
};

class Solution {//中序遍历迭代
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root==NULL)  return res;
        stack<TreeNode*> st;
        TreeNode *cur=root;
        while(cur!=NULL||!st.empty()){
            //先将所有左结点压入栈中(在将左结点压入栈中时,其根节点也会压入栈中)
            if(cur!=NULL){
                st.push(cur);   //左
                cur=cur->left;  
            }
            //当结点为叶子结点时,输出该结点,并回到其根节点,将该根节点的右孩子压入栈中
            else{
                cur=st.top();
                st.pop();
                res.push_back(cur->val);    //根
                cur=cur->right;//右
            }
        }
        return res;
    }
};

class Solution {//统一迭代
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        if(root!=NULL)  st.push(root);
        TreeNode *cur=root;
        while(!st.empty()){
            TreeNode *cur=st.top();
            if(cur!=NULL){
                st.pop();//虽然之前将根节点push进栈,但处理结点顺序时将根节点pop出来,再按照前序/中序/后序将结点push进栈

                if(cur->right)  st.push(cur->right);//右
                st.push(cur);//根
                st.push(NULL);//根节点访问过但还没处理,加入空结点作为标记
                if(cur->left)   st.push(cur->left);//左
            }else{
                st.pop();//先把NULLpop出来

                cur=st.top();
                st.pop();
                res.push_back(cur->val);//按照push顺序处理结点
            }
        }
        return res;
    }
};

题目链接:145. 二叉树的后序遍历 - 力扣(LeetCode)

class Solution {//后序遍历递归
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root==NULL)  return res;
        traversal(root,res);
        return res;
    }
private:
    void traversal(TreeNode *cur,vector<int> &res){
        if(cur==NULL)   return ;
        traversal(cur->left,res);
        traversal(cur->right,res);
        res.push_back(cur->val);
    }
};

class Solution {//后序遍历迭代
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        if(root==NULL)  return res;
        stack<TreeNode*> st;
        st.push(root);
        while(!st.empty()){
            TreeNode *node=st.top();
            st.pop();
            res.push_back(node->val);               //根
            if(node->left)  st.push(node->left);    //左
            if(node->right) st.push(node->right);   //右
        }
        //按照以上得到的是根右左的序列,反转一下就是左右根
        reverse(res.begin(),res.end());
        return res;
    }
};

class Solution {//后序遍历统一迭代
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> st;
        if(root!=NULL)  st.push(root);
        while(!st.empty()){
            TreeNode *cur=st.top();
            if(cur!=NULL){
                st.pop();
                
                st.push(cur);//根
                st.push(NULL);//虽然根已经刚问过但还没有处理,push空结点作为标记
                if(cur->right)   st.push(cur->right);//右
                if(cur->left)  st.push(cur->left);//左
            }
            else{
                st.pop();//pop出NULL
                cur=st.top();
                st.pop();
                res.push_back(cur->val);
            }
        }
        return res;
    }
};

题目链接:589. N 叉树的前序遍历 - 力扣(LeetCode)

class Solution {//递归
public:
    vector<int> preorder(Node* root) {
        vector<int> res;
        if(root==NULL)  return res;
        travel(root,res);
        return res;
    }
private:
    void travel(Node* root,vector<int> &res){
        res.push_back(root->val);
        //由上面Node的定义可知,children是一个vector<Node*>数组
        for(int i=0;i<root->children.size();i++)
        {
            travel(root->children[i],res);
        }
    }
};

class Solution {//迭代
public:
    vector<int> preorder(Node* root) {
        vector<int> res;
        if(root==NULL)  return res;
        stack<Node*> st;
        st.push(root);
        while(!st.empty()){
            Node *node=st.top();
            st.pop();
            res.push_back(node->val);
            for(int i=node->children.size()-1;i>=0;i--)
            {
                st.push(node->children[i]);
            }
        }
        return res;
    }
};

题目链接:590. N 叉树的后序遍历 - 力扣(LeetCode)

class Solution {//递归
public:
    vector<int> postorder(Node* root) {
        vector<int> res;
        if(root==NULL)  return res;
        order(root,res);
        return res;
    }
private:
    void order(Node *cur,vector<int> &res){
        if(cur==NULL)  return ;
        for(int i=0;i<cur->children.size();i++){
            order(cur->children[i],res);
        }
        res.push_back(cur->val);
    }
};

class Solution {//迭代
public:
    vector<int> postorder(Node* root) {
        vector<int> res;
        if(root==NULL)  return res;
        stack<Node*> st;
        st.push(root);
        while(!st.empty()){
            Node *cur=st.top();
            st.pop();
            //在N叉树的前序遍历中,children是倒序push的
            for(int i=0;i<cur->children.size();i++){
                st.push(cur->children[i]);
            }
            res.push_back(cur->val);
        }
        //N叉树的后序遍历要反转
        reverse(res.begin(),res.end());
        return res;
    }
};

题目链接:102. 二叉树的层序遍历 - 力扣(LeetCode)

class Solution {//迭代
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        //辅助队列
        queue<TreeNode*> q;
        //每一层形成一个数组
        vector<vector<int>> res;
        if(root!=NULL)  q.push(root);
        while(!q.empty())
        {
            //记录每一层的结点数
            int size=q.size();
            vector<int> r;
            for(int i=0;i<size;i++)
            {
                TreeNode *cur=q.front();
                //如果该结点有左右孩子就压入队列
                if(cur->left)   q.push(cur->left);
                if(cur->right)  q.push(cur->right);
                r.push_back(cur->val);
                q.pop();
            }
            res.push_back(r);
        }
        return res;
    }
};

class Solution {//递归
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        int depth=0;
        order(root,res,depth);
        return res;
    }
private:
    void order(TreeNode *cur,vector<vector<int>> &res,int depth){
        if(cur==NULL)   return;
        //如果res目前的数组数==depth,则需要新建一层数组
        if(res.size()==depth)   res.push_back(vector<int>());
        res[depth].push_back(cur->val);
        order(cur->left,res,depth+1);
        order(cur->right,res,depth+1);
    }
};

题目链接:107. 二叉树的层序遍历 II - 力扣(LeetCode)

class Solution {
public:
    vector<vector<int>> levelOrderBottom(TreeNode* root) {
        queue<TreeNode*> q;
        vector<vector<int>> res;
        if(root!=NULL)  q.push(root);
        while(!q.empty()){
            int size=q.size();
            vector<int> r;
            for(int i=0;i<size;i++){
                TreeNode *cur=q.front();
                r.push_back(cur->val);
                if(cur->left)   q.push(cur->left);
                if(cur->right)  q.push(cur->right);
                q.pop();
            }
            res.push_back(r);
        }
        //反转层次遍历数组
        reverse(res.begin(),res.end());
        return res;
    }
};

题目链接:199. 二叉树的右视图 - 力扣(LeetCode)

class Solution {
public:
    vector<int> rightSideView(TreeNode* root) {
        queue<TreeNode*> q;
        vector<int> res;
        if(root!=NULL)  q.push(root);
        while(!q.empty())
        {
            int size=q.size();
            for(int i=0;i<size;i++){
                TreeNode *cur=q.front();
                if(cur->left)   q.push(cur->left);
                if(cur->right)  q.push(cur->right);
                q.pop();
                //取每层最后一个结点
                if(i==size-1)   res.push_back(cur->val);
            }
        }
        return res;
    }
};

 题目链接:637. 二叉树的层平均值 题解 - 力扣(LeetCode)

class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
        //层次遍历并计算每层平均值
        vector<double> res;
        queue<TreeNode*> q;
        if(root!=NULL)  q.push(root);
        while(!q.empty()){
            int size=q.size();
            double sum=0;
            for(int i=0;i<size;i++){
                TreeNode *cur=q.front();
                q.pop();
                sum+=cur->val;
                if(cur->left)   q.push(cur->left);
                if(cur->right)  q.push(cur->right);
            }
            res.push_back(sum/size);
        }
        return res;
    }
};

题目链接:429. N 叉树的层序遍历 - 力扣(LeetCode)

class Solution {//迭代
public:
    vector<vector<int>> levelOrder(Node* root) {
        vector<vector<int>> res;
        queue<Node*> q;
        if(root!=NULL)  q.push(root);
        while(!q.empty()){
            int size=q.size();
            vector<int> r;
            for(int i=0;i<size;i++)
            {
                Node *cur=q.front();
                q.pop();
                r.push_back(cur->val);
                for(int j=0;j<cur->children.size();j++){
                    q.push(cur->children[j]);
                }
            }
            res.push_back(r);
        }
        return res;
    }
};

题目链接:515. 在每个树行中找最大值 - 力扣(LeetCode)

class Solution {
public:
    vector<int> largestValues(TreeNode* root) {
        vector<int> res;
        queue<TreeNode*> q;
        if(root!=NULL)  q.push(root);
        while(!q.empty()){
            int size=q.size();
            int max=INT_MIN;
            for(int i=0;i<size;i++){
                TreeNode *cur=q.front();
                q.pop();
                if(cur->val>max)    max=cur->val;
                if(cur->left)   q.push(cur->left);
                if(cur->right)  q.push(cur->right);
            }
            res.push_back(max);
        }
        return res;
    }
};

题目链接:116. 填充每个节点的下一个右侧节点指针 - 力扣(LeetCode)

class Solution {
public:
    Node* connect(Node* root) {
        queue<Node*> q;
        if(root!=NULL)  q.push(root);
        while(!q.empty()){
            int size=q.size();
            for(int i=0;i<size;i++){
                Node *cur=q.front();
                q.pop();
                //当cur指向每层最后一个结点时,令其next指向NULL,否则指向该层下一个结点
                if(i==size-1)   cur->next=NULL;
                else    cur->next=q.front();
                if(cur->left)   q.push(cur->left);
                if(cur->right)  q.push(cur->right);
            }
        }
        return root;
    }
};

题目链接:117. 填充每个节点的下一个右侧节点指针 II - 力扣(LeetCode)

//当父结点不为空时
//如果父结点cur有左孩子
    //如果temp为空,则说明当前结点cur->left是该层第一个结点,记录下来,下一层的父结点从temp开始;如果temp不为空,则当前结点不是该层第一个结点
    //如果last不为空,则令last->next=当前结点;如果last为空,说明当前结点是该层第一个结点。不管last空不空都要给last赋值当前结点
    //当前结点的next=当前父结点的right
//如果父结点cur有右孩子
    //如果temp为空,同左孩子的temp情况
    //如果last为空,同左孩子的last情况
    //如果父结点的next不为空,则cur=cur->next,继续该层下一个父结点的孩子遍历;如果父结点的next为空,则cur=temp,进行下一层遍历
class Solution {
public:
    Node* connect(Node* root) {
        //cur表示当前遍历到的结点的父结点
        //temp表示同一层第一个访问的结点
        //last表示同一层上一个不为空的结点
        Node *cur=root,*temp=NULL,*last=NULL;
        while(cur){
            if(cur->left){
                if(!temp)   temp=cur->left;
                if(last)    last->next=cur->left;
                cur->left->next=cur->right,last=cur->left;
            }
            if(cur->right){
                if(!temp)   temp=cur->right;
                if(last)    last->next=cur->right;
                if(cur->next)   cur->right->next=cur->next->left,last=cur->right;
            }
            if(cur->next)   cur=cur->next;
            else    cur=temp,temp=NULL,last=NULL;
        }
        return root;
    }
};

题目链接:104. 二叉树的最大深度 - 力扣(LeetCode)

class Solution {//深度优先遍历
public:
    int maxDepth(TreeNode* root) {
        if(root==NULL)  return 0;
        return max(maxDepth(root->left),maxDepth(root->right))+1;
    }
};

class Solution {//广度优先遍历
public:
    int maxDepth(TreeNode* root) {
        if(root==NULL)  return 0;
        queue<TreeNode*> q;
        int depth=0;
        q.push(root);
        while(!q.empty()){
            int size=q.size();
            depth++;
            for(int i=0;i<size;i++){
                TreeNode *cur=q.front();
                q.pop();
                if(cur->left)   q.push(cur->left);
                if(cur->right)  q.push(cur->right);
            }
        }
        return depth;
    }
};

题目链接:111. 二叉树的最小深度 - 力扣(LeetCode)

class Solution {
public:
    int minDepth(TreeNode* root) {
        int depth=0;
        queue<TreeNode*> q;
        if(root==NULL)  return 0;
        q.push(root);
        while(!q.empty()){
            int size=q.size();
            depth++;
            for(int i=0;i<size;i++){
                TreeNode *cur=q.front();
                q.pop();
                if(cur->left)   q.push(cur->left);
                if(cur->right)  q.push(cur->right);
                //不必比较depth的大小,因为这是层次遍历,只要该结点为叶子节点就一定是最小的深度
                if(cur->left==NULL&&cur->right==NULL)   return depth;
            }
        }
        return depth;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值