先序:先訪問根,然後訪問左子樹,然後訪問右子樹。中->左->右
實現方法:
1)初始化,將根節點放入棧
2)從棧頂取節點,彈棧並打印,有右孩子先壓右孩子,再壓左孩子
3)重複2)至棧空。
分析:由於我們每次都是將左孩子壓在最頂,保證了在遍歷子樹的時候,是先左後右的。
代碼:https://www.lintcode.com/problem/binary-tree-preorder-traversal/description
vector<int> preorderTraversal(TreeNode * root) {
// write your code here
vector<int>result;
if(!root)return result;
stack<TreeNode*>sta;
sta.push(root);
TreeNode* now;
while(!sta.empty()){
now=sta.top();
sta.pop();
result.push_back(now->val);
if(now->right)sta.push(now->right);
if(now->left)sta.push(now->left);
}
return result;
}
中序:先訪問左子樹,然後訪問根,然後訪問右子樹。左->中->右
1)初始化,cur=root
2)if cur!=NULL ,將cur壓入棧,cur=cur->left
3)else if cur==NULL,彈棧並打印,cur=cur.right
4)重複2)~3)。
分析:我們是將左鏈壓入棧,只有在遇到空孩子的時候纔打印,而整個左鏈彈棧輸出的順序是一定會滿足左孩子比根先打印的,因爲在棧內,左孩子永遠比他父親更靠近棧頂。
代碼:https://www.lintcode.com/problem/binary-tree-inorder-traversal/description
vector<int> inorderTraversal(TreeNode * root) {
// write your code here
stack<TreeNode*>sta;
vector<int>result;
if(!root)return result;
TreeNode* cur=root;
sta.push(cur);
cur=cur->left;
while(true){
if(cur){
sta.push(cur);
cur=cur->left;
}else{
if(sta.empty())return result;
cur=sta.top();
result.push_back(cur->val);
sta.pop();
cur=cur->right;
}
}
}
後序:先訪問左子樹,然後訪問右子樹,然後訪問根。左->右->中
我們無法直接考慮後序的方式輸出,但是我們可以借用前面的遍歷打印後序。我們可以藉由一個棧將打印順序逆序,於是我們要打印左->右->中可以變爲打印中->右->左。
策略:將先序遍歷的訪問改爲先左孩子再右,打印改爲將要打印的元素壓入output棧,最後將output棧輸出至空即可。
代碼:https://www.lintcode.com/problem/binary-tree-postorder-traversal/description
vector<int> postorderTraversal(TreeNode * root) {
// write your code here
vector<int>result;
TreeNode* now;
stack<int>output;
stack<TreeNode*>input;
if(!root)return result;
input.push(root);
while(!input.empty()){
now=input.top();
output.push(now->val);
input.pop();
if(now->left){
input.push(now->left);
}
if(now->right)input.push(now->right);
}
while(!output.empty()){
result.push_back(output.top());
output.pop();
}
return result;
}