二叉樹的迭代遍歷


二叉樹的迭代遍歷

題目鏈接

144.二叉樹的前序遍歷(簡單)

94.二叉樹的中序遍歷(簡單)

145.二叉樹的后序遍歷(簡單)

題解

用迭代法(非遞歸的方式)來實現二叉樹的前中后序遍歷。

遞歸的實現就是:每一次遞歸調用都會把函數的局部變量、參數值和返回地址等壓入調用棧中,然后遞歸返回的時候,從棧頂彈出上一次遞歸的各項參數,所以這就是遞歸為什么可以返回上一層位置的原因。

前序遍歷(迭代法)

思路:前序遍歷是中左右,每次先處理的是中間節點,那么先將根節點放入棧中,然后將右孩子加入棧,再加入左孩子。這樣才能保證出棧時的順序是中左右。如下所示:

代碼(C++):

//二叉樹的前序遍歷(迭代)
class Solution1 {
public:
    vector<int> preorderTraversal(TreeNode *root) {
        //先定義一個棧,棧中存放元素的類型為指向樹節點的指針
        stack<TreeNode*> sta;
        //再定義一個vector,用於存放結果
        vector<int> result;
        if (root == nullptr) return result;
        else sta.push(root);
        while (!sta.empty()) {
            result.push_back(sta.top()->val); //
            TreeNode *node = sta.top();
            sta.pop();
            //注意左節點或右節點為空時是不入棧的
            if(node->right != nullptr) sta.push(node->right); //
            if(node->left != nullptr) sta.push(node->left); //
        }
        return result;
    }
};

分析:

  • 時間復雜度:O(n),其中 n 是二叉樹的節點數

  • 空間復雜度:O(n),為迭代過程中顯式棧的開銷,平均情況下為 O(logn),最壞情況下樹呈現鏈狀,為 O(n)。

中序遍歷(迭代法)

思路:

不能直接改一下上面前序遍歷代碼的順序來實現中序遍歷。

在上面的前序遍歷中有兩個操作:

  1. 處理:將元素放進result數組中

  2. 訪問:遍歷節點

前序遍歷的順序是中左右,先訪問的元素是中間節點,要處理的元素也是中間節點,所以能寫出相對簡潔的代碼,因為要訪問的元素和要處理的元素順序是一致的,都是中間節點。

而中序遍歷是左中右,先訪問的是二叉樹頂部的節點,然后一層一層向下訪問,直到到達樹左面的最底部,再開始處理節點(也就是在把節點的數值放進result數組中),這就造成了處理順序和訪問順序是不一致的。

那么在使用迭代法寫中序遍歷,就需要借用指針的遍歷來幫助訪問節點,棧則用來處理節點上的元素。如下所示:

代碼(C++):

//二叉樹的中序遍歷(迭代)
class Solution2 {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        stack<TreeNode*> sta;
        vector<int> result;
        TreeNode* node = root;
        while (node != nullptr || !sta.empty()) {
            if (node != nullptr) {
                sta.push(node);
                node = node->left;
            } else {
                node = sta.top();
                sta.pop();
                result.push_back(node->val);
                node = node->right;
            }
        }
        return result;
    }
};

分析:

  • 時間復雜度:O(n),其中 n 為二叉樹節點的個數。

  • 空間復雜度:O(n),空間復雜度取決於棧深度,最壞情況下樹呈現鏈狀,為 O(n)。

后序遍歷(迭代法)

思路:先序遍歷是中左右,后續遍歷是左右中,那么只需要調整一下先序遍歷的代碼順序,就變成中右左的遍歷順序,然后在反轉result數組,輸出的結果順序就是左右中了,如下圖:

代碼(C++):

//二叉樹的后序遍歷(迭代)
class Solution3 {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> sta;
        vector<int> result;
        if (root == nullptr) return result;
        else sta.push(root);
        while (!sta.empty()) {
            TreeNode* node = sta.top();
            sta.pop();
            result.push_back(node->val);
            if(node->left != nullptr) sta.push(node->left);
            if(node->right != nullptr) sta.push(node->right);
        }
        reverse(result.begin(), result.end());
        return result;
    }
};

分析:

  • 時間復雜度:O(N)

  • 空間復雜度:O(N)(最壞情況下)

參考鏈接

代碼隨想錄

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM