二叉樹的非遞迴遍歷:棧---->最簡潔,最容易版.
阿新 • • 發佈:2019-02-09
後序遍歷(左->右->根):需要一個標記Lastvisited
只有兩種情況才能彈出棧,1.右孩子節點為空,2.右孩子節點已經訪問過(如果沒有這條,那麼會死迴圈再次push該孩子的右節點)中序遍歷:(左->根->右) 簡單,不需要已訪問標記,只需要在彈出去的那一刻,把他的所有子節點進棧即可。/** * 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; if(root==NULL) return res; stack<TreeNode*> st; while(root) { st.push(root); root=root->left; } TreeNode* LastVisted=NULL;//標記已經訪問過的,不然會再次進棧。 while(!st.empty()) { TreeNode* top=st.top(); if(top->right==NULL||top->right==LastVisted)//右孩子節點為空,或者右孩子節點已經訪問過。 { st.pop(); LastVisted=top; res.push_back(top->val); }else { TreeNode *p=top->right; while(p) { st.push(p); p=p->left; } } } return res; } };
/** * 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; if(root==NULL) return res; stack<TreeNode*> st; while(root) { st.push(root); root=root->left; } while(!st.empty()) { TreeNode*top=st.top(); st.pop(); res.push_back(top->val); TreeNode*p=top->right; while(p) { st.push(p); p=p->left; } } return res; } };
先序遍歷:根->左->右 這個想法我沒想到,中序、後序我都是直接把左節點全部進棧,然後再一個一個彈出來再處理,先序遍歷,則可以邊彈出邊進棧,從根節點開始就進行。 唯獨,先序遍歷不需要先把左孩子全部進棧,因為它一開始就遍歷根節點,所以,只要按照先進棧右節點,再進棧左節點的方式即可。
/** * 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; if(root==NULL) return res; stack<TreeNode*> st; st.push(root); while(!st.empty()) { TreeNode*top=st.top(); st.pop(); res.push_back(top->val); if(top->right) st.push(top->right); if(top->left) st.push(top->left); } return res; } };
總結: 1.中序,後序遍歷,因為都是"左"在前面,所以首先要依次進棧左孩子節點,然後彈出棧開始下一步處理。 2.這裡,後序遍歷需要一個訪問標記,只有該孩子的右孩子節點為空,或者右孩子已經訪問過,才彈出棧。 3.先序遍歷,因為最先開始遍歷根節點,所以採取的策略是一邊遍歷,一邊進棧,而不是全部把左孩子進棧。