先序:先访问根,然后访问左子树,然后访问右子树。中->左->右
实现方法:
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;
}