代码训练营DAY13 第六章 二叉树part01

理论基础

二叉树种类
存储方式

遍历方式  深度优先搜索&广度优先搜索

深度:前序遍历、中序遍历、后序遍历(中间在前or中or后,左右顺序固定)

广度:

二叉树定义

递归遍历 (必须掌握)

递归分析三步法

1、确定递归函数的参数返回值

2、确定终止条件

3、确定单层递归逻辑

前序遍历

144. 二叉树的前序遍历 - 力扣(LeetCode)

/**
 * 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:
    void taversal(TreeNode* cur,vector &vec){
        if(cur==NULL)return;
        vec.push_back(cur->val);
        taversal(cur->left,vec);
        taversal(cur->right,vec);
    }
    vector preorderTraversal(TreeNode* root) {
        vector res;
        taversal(root,res);
        return res;
    }
};

后序遍历

145. 二叉树的后序遍历 - 力扣(LeetCode)

/**
 * 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:
    void taversal(TreeNode* cur,vector &vec){
        if(cur==NULL){return;}
        taversal(cur->left,vec);
        taversal(cur->right,vec);
        vec.push_back(cur->val);
    }
    vector postorderTraversal(TreeNode* root) {
        vector res;
        taversal(root,res);
        return res;
    }
};

中序遍历

94. 二叉树的中序遍历 - 力扣(LeetCode)

/**
 * 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:
    void traversal(TreeNode*cur,vector &vec){
        if(cur==NULL)return;
        
        traversal(cur->left,vec);
        vec.push_back(cur->val);
        traversal(cur->right,vec);
    }
    vector inorderTraversal(TreeNode* root) {
        vector res;
        traversal(root,res);
        return res;
    }
};

二叉树的迭代遍历

思路:用栈作为中间容器,前序遍历是”中左右“根节点不为空时将根节点放入栈,使用while循环,循环条件是栈不为空,循环中首先引入一个Node节点记录栈顶的节点,然后pop掉栈里的顶部元素,将这个元素的值Node->val赋值给res结果,然后先push进栈node->right,再是node->left;因为出栈顺序是后进先出,从而实现中左右的前序遍历顺序。

前序遍历

/**
 * 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 preorderTraversal(TreeNode* root) { 
        stack st; 
        vector res;
        if(root==NULL)return res;
        st.push(root);
        while(!st.empty()){
            TreeNode* Node=st.top();
            st.pop();
            res.push_back(Node->val);
            if(Node->right!=NULL){st.push(Node->right);}
            if(Node->left!=NULL){st.push(Node->left);}
        }
        return res;
    }
};

中序遍历

中序遍历的顺序是左中右,指针元素与操作元素与前序遍历不同,所以结构不同;这里还需要引入一个遍历指针cur,先指向root,遍历中向左(cur=cur->left)直到底层,每次循环将结点存入栈中,结束时cur==NULL,此时将cur=st.top()即为底层的左元素,要将其存入res,然后pop掉;下一个top即“中节点”,处理完中结点后cur=cur->right,移动到右节点。进行下一次迭代。

/**
 * 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 inorderTraversal(TreeNode* root) {
        stack st;
        vector res;
        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;
    }
};

后序遍历

/**
 * 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 postorderTraversal(TreeNode* root) {
        stack st;
        vector res;
        if(root==NULL){return res;}
        st.push(root);
        while(!st.empty()){
            TreeNode* tmp=st.top();   
            st.pop();      
            res.push_back(tmp->val);
            if(tmp->left){st.push(tmp->left);}
            if(tmp->right){st.push(tmp->right);}
        }
        reverse(res.begin(),res.end());
        return res;
    }
};

统一格式的迭代法遍历 我打算用空结点方法

前序遍历

class Solution {
public:
    vector inorderTraversal(TreeNode* root) {
        vector result;
        stack 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);  // 添加右节点(空节点不入栈)
                if (node->left) st.push(node->left);    // 添加左节点(空节点不入栈)
                st.push(node);                          // 添加中节点
                st.push(NULL); // 中节点访问过,但是还没有处理,加入空节点做为标记。

                
            } else { // 只有遇到空节点的时候,才将下一个节点放进结果集
                st.pop();           // 将空节点弹出
                node = st.top();    // 重新取出栈中元素
                st.pop();
                result.push_back(node->val); // 加入到结果集
            }
        }
        return result;
    }
};

中序遍历

class Solution {
public:
    vector inorderTraversal(TreeNode* root) {
        vector result;
        stack 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;
    }
};

后续遍历

class Solution {
public:
    vector inorderTraversal(TreeNode* root) {
        vector result;
        stack 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;
    }
};

这个办法妙啊,在while中先pop掉之前的中间元素,再按照目标的逆序push,push完中间节点就继续加一个null标记

102.二叉树的层序遍历

102. 二叉树的层序遍历 - 力扣(LeetCode)

解题思路:

用队列作为容器,首先放入root,当队列不为空时进入循环;循环中,引入size=每一层节点的数量,引入vec记录每一层的节点值,在for循环中遍历每一层的节点,在vec中记录节点值并将其非空的左右儿子加入队列;for循环后在res中记录每一层的vec。

/**
 * 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> levelOrder(TreeNode* root) {
        vector> res;
        
        queue que;
        if(root!=NULL)que.push(root);
        while(!que.empty()){
           int size=que.size();
            vector vec;
            for(int i=0;ival);
                if(node->left){que.push(node->left);}
                if(node->right){que.push(node->right);}
            }
            res.push_back(vec);
        }
    return res;
    }
};

107.二叉树的层次遍历 II

107. 二叉树的层序遍历 II - 力扣(LeetCode)

在上一题的基础上,输出前反转一下res。

/**
 * 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> levelOrderBottom(TreeNode* root) {
        vector> res;
        queue que;
        if(root!=NULL)que.push(root);
        while(!que.empty()){
           int size=que.size();
            vector vec;
            for(int i=0;ival);
                if(node->left){que.push(node->left);}
                if(node->right){que.push(node->right);}
            }
            res.push_back(vec);
        }
    reverse(res.begin(),res.end());//只需要反转一下最后的输出
    return res;
    }
};

199.二叉树的右视图

199. 二叉树的右视图 - 力扣(LeetCode)

/**
 * 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 rightSideView(TreeNode* root) {
        vector res;
        queue que;
        if(root!=NULL)que.push(root);
        while(!que.empty()){
           int size=que.size();
            
            for(int i=0;ival);}//只需要将每一层的最后一个元素记录
                if(node->left){que.push(node->left);}
                if(node->right){que.push(node->right);}
            }
        }
    return res;
    }
};

637.二叉树的层平均值

637. 二叉树的层平均值 - 力扣(LeetCode)

在循环中引入sum,for循环中sum+=node->val;for循环结束后用res记录均值sum/size。注意使用double res、sum

/**
 * 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 averageOfLevels(TreeNode* root) {
        vector res;
        
        queue que;
        if(root!=NULL)que.push(root);
        while(!que.empty()){
           int size=que.size();
            double sum=0;
            for(int i=0;ival;
                if(node->left){que.push(node->left);}
                if(node->right){que.push(node->right);}
            }
            res.push_back(sum/size);
        }
    return res;
    }
};

429.N叉树的层序遍历

429. N 叉树的层序遍历 - 力扣(LeetCode)

for循环中再套一层for循环用于遍历每个结点的孩子节点,原来是只有left和right两个儿子

/*
// Definition for a Node.
class Node {
public:
    int val;
    vector children;

    Node() {}

    Node(int _val) {
        val = _val;
    }

    Node(int _val, vector _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
public:
    vector> levelOrder(Node* root) {
       
        queue que;
        if (root != NULL) que.push(root);
        vector> result;
        while (!que.empty()) {
            int size = que.size();
            vector vec;
            for (int i = 0; i < size; i++) {
                Node* node = que.front();
                que.pop();
                vec.push_back(node->val);
                for (int i = 0; i < node->children.size(); i++) { // 将节点孩子加入队列
                    if (node->children[i]) que.push(node->children[i]);
                }
            }
            result.push_back(vec);
        }
        return result;
    }
};

515.在每个树行中找最大值

515. 在每个树行中找最大值 - 力扣(LeetCode)

引入一个maxValue,在for循环中比较node->val与maxValue,取最大值;

maxValue=node->val>maxValue? node->val:maxValue;

for循环后将最大值记录在res中。

/**
 * 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 largestValues(TreeNode* root) {
        vector res;
        queue que;
        if(root!=NULL)que.push(root);
        while(!que.empty()){
           int size=que.size();
           int maxValue = INT_MIN;
            for(int i=0;ival>maxValue? node->val:maxValue;
                if(node->left){que.push(node->left);}
                if(node->right){que.push(node->right);}
            }
            res.push_back(maxValue);
        }
    return res;
    }
};

116.填充每个节点的下一个右侧节点指针

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

for循环前引入两个指针nodePre和node,nodePre表示每一行中当前节点的左侧节点,若是开头i=0则nodePre=que.top();非开头node=que.top();

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};
*/

class Solution {
public:
    Node* connect(Node* root) {
        queue que;
        if(root!=NULL)que.push(root);
        while(!que.empty()){
            int size=que.size();//很关键
            //vector vec;
            Node* nodePre;
            Node* node;
            for(int i=0;inext=node;
                    nodePre=nodePre->next;
                }
                if(node->left)que.push(node->left);
                if(node->right)que.push(node->right);
            }
        nodePre->next=NULL;
        }
        return root;
    }
};

117.填充每个节点的下一个右侧节点指针II

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

和上一题答案完全一样,因为已经能够让空指针不入队,

if(node->left)que.push(node->left);
if(node->right)que.push(node->right);

104.二叉树的最大深度

104. 二叉树的最大深度 - 力扣(LeetCode)

引入深度,在for循环中 每轮depth+1;就是深度

/**
 * 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:
    int maxDepth(TreeNode* root) {
        if (root == NULL)
            return 0;
        int depth = 0;
        queue que;
        if (root != NULL)
            que.push(root);
        while (!que.empty()) {
            int size = que.size(); // 很关键
            depth++;
            for (int i = 0; i < size; i++) {

                TreeNode* tmp = que.front();
                que.pop();

                if (tmp->left)
                    que.push(tmp->left);
                if (tmp->right)
                    que.push(tmp->right);
            }
        }

        return depth;
    }
};

111.二叉树的最小深度

111. 二叉树的最小深度 - 力扣(LeetCode)

解题思路:

只有左儿子右儿子都为空时才能算最浅的底部。

/**
 * 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:
    int minDepth(TreeNode* root) {
        if (root == NULL)
            return 0;
        int depth = 0;
        queue que;
        if (root != NULL)
            que.push(root);
        while (!que.empty()) {
            int size = que.size(); // 很关键
            depth++;
            for (int i = 0; i < size; i++) {

                TreeNode* tmp = que.front();
                que.pop();
                if (tmp->left)
                    que.push(tmp->left);
                if (tmp->right)
                    que.push(tmp->right);
                if (tmp->left==NULL&&tmp->right==NULL){return depth;}
                
            }
            
        }

        return depth;
    }
};

你可能感兴趣的:(数据结构,算法)