二叉树的前序,中序,后序遍历的非递归版本有许多种。
较为简单的是采用栈,来模拟递归。
此外,还可以采用标记,或者父亲指针来实现。这些算法都需要 O(n)的空间,
还有一类算法仅仅需要常数的空间即可。如 Morris 遍历 http://blog.csdn.net/shoulinjun/article/details/19051503
前序和中序相对比较简单,代码仅仅相差一行。后序相对比较复杂,需要记录右子树是否已经访问。
前序遍历:
void PreOrderVisitStack(struct TreeNode * root)
{
stack<TreeNode*> s;
while(root != NULL || !s.empty())
{
while(root){
cout << root->value << " ";
s.push(root);
root = root->left_child;
}
if(!s.empty()){
root = s.top(); s.pop();
root = root->right_child;
}
}
}
void InOrderVisitStack(TreeNode *root)
{
stack<TreeNode*> s;
while(root != NULL || !s.empty())
{
while(root){
s.push(root);
root = root->left_child;
}
if(!s.empty()){
root = s.top(); s.pop();
cout << root->value << " ";
root = root->right_child;
}
}
}
后序遍历:
用 pre 记录前一个访问的节点,如果 root 的右孩子是 pre 或者 NULL, 说明右子树已经访问,这时访问 root 即可。
void PostOrderVisitStack(TreeNode *root)
{
stack<TreeNode*> s;
TreeNode *pre(NULL); //前一部访问的节点
while(root || !s.empty())
{
while(root){
s.push(root);
root = root->left_child;
}
if(!s.empty()){
root = s.top(); s.pop();
// right_child already visited
if(root->right_child == pre || root->right_child == NULL){
cout << root->value << " ";
pre = root;
root = NULL;
}
else{
s.push(root);
root = root->right_child;
}
}
}//end while
}