程式碼隨想錄演算法訓練營第十四天 | 二叉樹遍歷

深蓝von發表於2024-05-22

遞迴法

文章講解 影片講解
遞迴三要素:
1 確定遞迴函式的引數和返回值
2 確定終止條件
3 確定單層遞迴的邏輯

前序遍歷

題目連結

  1. 遞迴的引數和返回值:傳入當前節點和儲存結果集的陣列,不需要返回值
  2. 終止條件:當前節點為空時
  3. 單層遞迴邏輯:儲存當前節點的值到結果集中
class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        traversal(root, ans);
        return ans;
    }
    void traversal(TreeNode* node, vector<int>& ans) {
        if(node == nullptr) return ;
        ans.push_back(node->val);  // 根
        traversal(node->left, ans);  // 左
        traversal(node->right, ans);  // 右
    }
};

中序遍歷

題目連結

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;
        traversal(root, ans);
        return ans;
    }
    void traversal(TreeNode* node, vector<int>& ans){
        if(node == nullptr) return ;
        traversal(node->left, ans);  // 左
        ans.push_back(node->val);  // 根
        traversal(node->right, ans);  // 右
    }
};

後序遍歷

題目連結

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ans;
        traversal(root, ans);
        return ans;
    }
    void traversal(TreeNode* node, vector<int>& ans) {
        if(node == nullptr) return ;
        traversal(node->left, ans);  // 左
        traversal(node->right, ans);  // 右
        ans.push_back(node->val);  // 根
    }
};

迭代法

文章講解

思路:遞迴遍歷就是將當前結果儲存在棧中,等到返回的時候再從棧頂彈出儲存的結果,所以可以用棧來模擬遞迴的方式來實現堆二叉樹的遍歷

前序遍歷

影片講解

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> ans;
        stack<TreeNode*> st;
        if(root == nullptr) return {};
        st.push(root);
        while(!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            // 需調整入棧順序來保證出棧順序為根左右
            if(node == nullptr) continue;
            ans.push_back(node->val);  // 根
            st.push(node->right);  // 右
            st.push(node->left);  // 左
        }
        return ans;
    }
};

中序遍歷

影片講解

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> ans;
        stack<TreeNode*> st;
        TreeNode * cur = root;
        while(cur || !st.empty()) {
            if(cur) {
                st.push(cur);
                cur = cur->left;
            } else {
                cur = st.top();
                ans.push_back(cur->val);
                st.pop();
                cur = cur->right;
            }
        }
        return ans;
    }
};

後序遍歷

影片講解

思路:直接用棧來調整是很難滿足後續遍歷要求的會陷入複雜的邏輯判斷中;
這是可以觀察前序遍歷是根->左->右, 而後序遍歷是左->右->根,秩序調前序遍歷程式碼的入棧順序為先左後右,就可以得到:
根->右->左的順序,最後將陣列反轉就可以得到正確的順序

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        vector<int> ans;
        stack<TreeNode*> st;
        if(root == nullptr) return {};
        st.push(root);
        
        while(!st.empty()) {
            TreeNode* node = st.top();
            ans.push_back(node->val);
            st.pop();
            if(node->left) st.push(node->left);
            if(node->right) st.push(node->right);
        }
        reverse(ans.begin(), ans.end());


        return ans;
    }
};

相關文章