題目鏈接
題解
用迭代法(非遞歸的方式)來實現二叉樹的前中后序遍歷。
遞歸的實現就是:每一次遞歸調用都會把函數的局部變量、參數值和返回地址等壓入調用棧中,然后遞歸返回的時候,從棧頂彈出上一次遞歸的各項參數,所以這就是遞歸為什么可以返回上一層位置的原因。
前序遍歷(迭代法)
思路:前序遍歷是中左右,每次先處理的是中間節點,那么先將根節點放入棧中,然后將右孩子加入棧,再加入左孩子。這樣才能保證出棧時的順序是中左右。如下所示:
代碼(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)。
中序遍歷(迭代法)
思路:
不能直接改一下上面前序遍歷代碼的順序來實現中序遍歷。
在上面的前序遍歷中有兩個操作:
-
處理:將元素放進result數組中
-
訪問:遍歷節點
前序遍歷的順序是中左右,先訪問的元素是中間節點,要處理的元素也是中間節點,所以能寫出相對簡潔的代碼,因為要訪問的元素和要處理的元素順序是一致的,都是中間節點。
而中序遍歷是左中右,先訪問的是二叉樹頂部的節點,然后一層一層向下訪問,直到到達樹左面的最底部,再開始處理節點(也就是在把節點的數值放進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)(最壞情況下)
參考鏈接