二叉树的前序,中序,后序遍历的非递归版本有许多种。
较为简单的是采用栈,来模拟递归。
此外,还可以采用标记,或者父亲指针来实现。这些算法都需要 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 }
原文:http://blog.csdn.net/shoulinjun/article/details/19089155