二分木のプレオーダー、ミドルオーダー、ポストオーダートラバーサル、再帰バージョンと非再帰バージョン、レイヤーオーダートラバーサル

二分木のシーケンストラバーサル

アイデア:レイヤーシーケンストラバーサルにキューを使用します。各操作は、1つのレイヤーをトラバースし、現在のレイヤーの値をベクトルに格納し、現在のノードの左右のノードが空でない場合、それらはキューにスローされます。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    
    
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
    
    
        vector<vector<int>> ans;
        queue<TreeNode*> que;
        if(root) que.push(root);
        while(!que.empty()){
    
    
            int siz=que.size();
            vector<int> a;
            while(siz--){
    
    
                TreeNode* now=que.front();
                que.pop();
                a.push_back(now->val);
                if(now->left) que.push(now->left);
                if(now->right) que.push(now->right);
            }
            ans.push_back(a);
        }
        return ans;
    }
};


二分木のプレオーダートラバーサル

再帰

アイデア:プレオーダーは左右なので、最初に値をスタブし、次にdfsの左右のサブツリーをスタブします

/**
 * 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<int> ans;
    void dfs(TreeNode* root){
    
    
        if(!root) return ;
        ans.push_back(root->val);
        dfs(root->left);
        dfs(root->right);
    }
    vector<int> preorderTraversal(TreeNode* root) {
    
    
        dfs(root);
        return ans;
    }
};

非再帰的

アイデア:再帰は実際にはスタックであることがわかっているので、再帰的でない場合は、スタックを使用してシミュレートします。
次に、事前注文が左右に行われ、スタックの最上位が後で追加されるためです。
したがって、左ノードと右ノードをスタックにスローするときは、最初に右ノードをドロップし、次に左ノードをドロップして、スタックの一番上が左ノードになるようにする必要があります。

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


二分木のポストオーダートラバーサル

再帰

アイデア:後順は左右なので、最初に左右のサブツリーをdfsし、次に値をスタブ化します

/**
 * 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<int> ans;
    void dfs(TreeNode* root){
    
    
        if(!root) return ;
        dfs(root->left);
        dfs(root->right);
        ans.push_back(root->val);
    }
    vector<int> postorderTraversal(TreeNode* root) {
    
    
        dfs(root);
        return ans;
    }
};

非再帰的

アイデア:私たちは、行きがけが左右、および後順が左右されることを知っている私たちは前順、その後、逆(先行順)に保存されているノードの順序を逆にした場合は、左右の中心地です。以前の非によると、 -プレオーダートラバーサルの再帰バージョン。次に、左の息子を最初にスタックに配置し、次に右の息子をスタックに配置するように変更します。これは右中央と左中央で、ベクトル全体が左右に反転します。これが後順です。

/**
 * 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<int> ans;
    vector<int> postorderTraversal(TreeNode* root) {
    
    
        stack<TreeNode*> sta;
        if(root) sta.push(root);
        while(!sta.empty()){
    
    
            TreeNode* now=sta.top();
            sta.pop();
            ans.push_back(now->val);
            //与前序非递归相比,这两行顺序换了换而已
            if(now->left) sta.push(now->left);
            if(now->right) sta.push(now->right);
        }
        reverse(ans.begin(),ans.end());//中右左 反转  左右中
        return ans;
    }
};


二分木の順序通りの走査

再帰

アイデア:中央の順序は左、中央、右なので、最初に左側のサブツリーをdfsし、次に値をスタブし、最後に右側のサブツリーをdfsします。

/**
/**
 * 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<int> ans;
    void dfs(TreeNode* root){
    
    
        if(!root) return ;
        dfs(root->left);
        ans.push_back(root->val);
        dfs(root->right);
    }
    vector<int> inorderTraversal(TreeNode* root) {
    
    
        dfs(root);
        return ans;
    }
};

非再帰的

アイデア:以前の非再帰バージョンでは、実際には最初にノードの値をスタブ化するため、残念ながら、これは以前の非再帰アプローチとあまり一致していません。次に、中間の順序が左、中央、右であることがわかります。実際、左のサブツリーは常に再帰的です。
したがって、基本的な考え方は、南の壁にぶつかったり、振り返ったりしないことです。つまり、左側のサブツリーが空でない場合は、繰り返し続けます。
空ですか?すでに左側のサブツリーをトラバースした最後のノードを取得するので、右側のサブツリーのトラバースを開始します。そして、それは左、中央、右なので、右のサブツリーの左のサブツリーをトラバースし続けます。

/**
 * 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<int> ans;
    vector<int> inorderTraversal(TreeNode* root) {
    
    
        stack<TreeNode*> sta;
        while(root || !sta.empty()){
    
    
            if(root){
    
    		//没撞南墙 一直遍历左子树
                sta.push(root);		//保存过来的结点
                root=root->left;
            }
            else{
    
    			//撞墙了
                root=sta.top();//取出上一个遍历的点
                sta.pop();
                ans.push_back(root->val);//
                root=root->right;//开始跑右子树
            }
        }
        return ans;
    }
};

おすすめ

転載: blog.csdn.net/qq_43563669/article/details/113789887