ATM機案例3之選單操作類(五)
題目連結
題解
用迭代法(非遞迴的方式)來實現二叉樹的前中後序遍歷。
遞迴的實現就是:每一次遞迴呼叫都會把函式的區域性變數、引數值和返回地址等壓入呼叫棧中,然後遞迴返回的時候,從棧頂彈出上一次遞迴的各項引數,所以這就是遞迴為什麼可以返回上一層位置的原因。
前序遍歷(迭代法)
思路:前序遍歷是中左右,每次先處理的是中間節點,那麼先將根節點放入棧中,然後將右孩子加入棧,再加入左孩子。這樣才能保證出棧時的順序是中左右。如下所示:
程式碼(C++):
//二叉樹的前序遍歷(迭代) classSolution1 { 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)(最壞情況下)
參考連結