数据结构《11》----二叉树遍历的非递归版本(栈)

二叉树的前序,中序,后序遍历的非递归版本有许多种。

较为简单的是采用栈,来模拟递归。

此外,还可以采用标记,或者父亲指针来实现。这些算法都需要 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
}







   

你可能感兴趣的:(非递归,二叉树遍历)