二叉樹前序、中序、後序、層序遍歷的遞歸法與迭代法總結

1 迭代法

迭代法比遞歸法稍微複雜一點,但無非就是藉助棧或隊列來實現二叉樹的遍歷

1.1 前序遍歷(Leetcode 144)

  • 前序遍歷: 當棧不爲空或者root不爲空節點時,先遍歷、訪問、壓棧左節點,當左節點不存在時出棧訪問右節點
/**
 * 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<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> s;
        TreeNode* temp = root;
        // 當棧不爲空或者root不爲空節點時
        while(!s.empty() || temp){
        //`先遍歷、訪問、壓棧左節點`
            while(temp){
                s.push(temp);
                res.push_back(temp->val);
                temp = temp->left;
            }
        //當訪問節點不存在左子樹時,退棧對右子樹進行訪問
            temp = s.top();
            s.pop();
            temp = temp->right;
        }
        return res;
    }
};

1.2 中序遍歷(Leetcode 94)

  • 與前序遍歷類似,當棧不爲空或者root不爲空節點時,先遍歷、壓棧左節點,當左節點不存在時,出棧先訪問棧頂節點然後訪問右節點
/**
 * 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<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> s;
        TreeNode* temp = root;
        //當棧不爲空或則根節點不爲空節點時
        while(!s.empty() || temp){
            //先`遍歷、壓棧左節點`
            while(temp){
                s.push(temp);
                temp = temp->left;
            }
            //當`左節點不存在時`,出棧`先訪問棧頂節點`,`然後訪問右節點`
            temp = s.top();
            s.pop();
            res.push_back(temp->val);
            temp = temp->right;
        }
        return res;
    }
};

1.3 後序遍歷(Leetcode 145)

  • 與前序遍歷類似,只不過前序遍歷先遍歷、訪問、壓棧左節點,當左節點不存在時,出棧訪問右節點
  • 而後序遍歷當棧不爲空或者root不爲空節點時,先遍歷、訪問、壓棧右節點,當右節點不存在時,出棧訪問左節點,最後**翻轉數組**
/**
 * 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<int> postorderTraversal(TreeNode* root) {
        vector<int> res;
        stack<TreeNode*> s;
        TreeNode* tmp = root;
        while(!s.empty() || tmp){
            //先遍歷、訪問、壓棧右節點
            while(tmp){
                res.push_back(tmp->val);
                s.push(tmp);
                tmp = tmp->right;
            }
            //當右節點不存在時,出棧訪問左節點
            tmp = s.top();
            s.pop();
            tmp = tmp->left;
        }
        //最後翻轉數組
        reverse(res.begin(), res.end());
        return res;
    }
};

1.4 層序遍歷(Leetcode 102)

  • 使用隊列,按每一層從左到右的節點出現順序存儲節點
  • 求出每一層隊列的長度,每訪問隊列的一個頭節點,就把該節點出列
  • 判斷是否該節點有左子節點或右子節點,如果有,則加入到隊列尾,爲訪問下一層做準備
/**
 * 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>> res;
        if(!root)
            return res;
        // 使用隊列,按每一層從左到右的節點出現順序來存儲節點
        queue<TreeNode*> q;
        q.push(root);
        // 當隊列不爲空時
        while(!q.empty()){
            // 求出每一層隊列的長度,
            int qLen = q.size();
            vector<int> tmp;
            for(int i=0; i<qLen; ++i){
                // 每訪問隊列的一個頭節點,就把該節點出列
                TreeNode* t = q.front();
                q.pop();
                tmp.push_back(t->val);
                 // 並判斷是否該節點有左子節點或右子節點,如果有,則加入到隊列尾,爲訪問下一層做準備
                if(t->left) q.push(t->left);
                if(t->right) q.push(t->right);
            }
            res.push_back(tmp);
        }
        return res;
    }
};

2 遞歸法

代碼比較簡短,思路邏輯也很清晰。就是建立一個輔助函數,以實現遞歸。

2.1 前序遍歷(Leetcode 144)

/**
 * 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<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        helper(root, res);
        return res;
    }
    void helper(TreeNode* root, vector<int> &res){
        if(root){
            res.push_back(root->val);
           helper(root->left, res);
           helper(root->right, res);
        } 
        else return ;

    }
};

2.2 中序遍歷(Leetcode 94)

/**
 * 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<int> inorderTraversal(TreeNode* root) {
        vector<int> res;
        helper(root, res);
        return res;
    }

     void helper(TreeNode* root, vector<int> &res){
        if(root){
            helper(root->left, res);
            res.push_back(root->val);
            helper(root->right, res);
        } 
        else return ;
    }
};

2.3 後序遍歷(Leetcode 145)

/**
 * 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<int> postorderTraversal(TreeNode* root) {
         vector<int> res;
         helper(root, res);
         return res;
    }
    void helper(TreeNode* root, vector<int> &res){
        if(root){
            helper(root->left, res);
            helper(root->right, res);
            res.push_back(root->val);
        } 
        else return ;
    }
};

2.4 層序遍歷(Leetcode 102)

要點有幾個:

  • 利用depth變量記錄當前在第幾層(從0開始),進入下層時depth + 1
  • 如果depth >= vector.size()說明這一層還沒來過,這是第一次來,所以得擴容咯;
  • 因爲是前序遍歷,中-左-右,對於每一層來說,左邊的肯定比右邊先被遍歷到,實際上前序和中序結果都是一樣的。
/**
 * 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>> res;
        helper(root, 0, res);
        return res;
    }
    void helper(TreeNode *root, int depth, vector<vector<int>> &ans){
        if (!root) return ;
        if (depth >= ans.size())
            ans.push_back(vector<int> {});
        ans[depth].push_back(root->val);
        helper(root->left, depth + 1, ans);
        helper(root->right, depth + 1, ans);
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章