用栈实现二叉树的非递归遍历

1、前序遍历

        用栈来实现二叉树非递归的先序遍历,先序遍历的方式是根->左->右,按照栈的入站退栈方式,应该先入根节点然后根节点退出再入右孩子和左孩子,只要栈不为空证明还没有遍历完二叉树。

void PreOrder(BtNode *root)
{
	stack<BtNode*>s;			      //生成一个栈
	if (root != NULL)			      //如果传的root节点不为空,则将root入栈
	{
		s.push(root);				
	}
	while (!s.empty())                            //只要栈里还有节点
	{
		BtNode*top = s.top();		      //保存一下栈顶节点
		s.pop();			      //栈顶节点退栈
		cout << top->data << " ";             //打印出刚才的数据
		if (top->rightchild)                  //右孩子存在就入栈
		{
			s.push(top->rightchild);
		}
		if (top->leftchild)                   //左孩子存在就入栈
		{
			s.push(top->leftchild);            
		}
	}
	cout << endl;                               
}

2、中序遍历

     用栈来实现二叉树非递归的中序遍历,先序遍历的方式是左->根->右。

     入栈:用一个指针从root开始遍历左孩子并入栈。

     将栈顶元素输出再出栈(每次出栈的栈顶元素都是左孩子已经遍历或者没有左孩子),再把右孩子赋值给该指针,遍历右边的元素。

void InOrder(BtNode *p)
{
	stack<BtNode*>s;
	BtNode* cur = p;
	while(cur != NULL || !s.empty ())
	{
		while(cur != NULL)
		{
			s.push(cur);
			cur = cur->leftchild ;
		}
		BtNode* top = s.top ();
		s.pop();
		cout<<top->data<<" ";
		if(top->rightchild != NULL)
		{
			cur = top->rightchild;
		}
	}
	cout<<endl;
}

3、后序遍历

     用栈来实现二叉树非递归的中序遍历,先序遍历的方式是左->右->根。

     由于我们的访问只能从上到下,所以要多定义一个指针来保存已经被输出的节点,避免访问不到右孩子。

void PastOrder2(BtNode *p)
{
	BtNode* cur = p;
	BtNode* aftercur = p;
	stack<BtNode*>s;
	while(cur!=NULL || !s.empty() )
	{
		while(cur!=NULL)
		{
			s.push (cur );
			cur = cur->leftchild ;
		}
		BtNode*top = s.top();
		if(top->rightchild == NULL || aftercur == top->rightchild )
//	如果当前的top右孩子为NULL或者top是右孩子证明已经被遍历过,可以输出top了
		{
			s.pop();
			cout<<top->data<<" ";
			aftercur = top;
		}
		else
			cur = top->rightchild;
	}
	cout<<endl;
}

总结:普通的二叉树都是从根节点开始向下遍历,访问到左边之后得退回到根节点再访问右边。所以:

          前序遍历:根->左->右  先入栈出栈根节点,然后打印。再从上到下右孩子入栈,左孩子入栈。当左边不能进行了,打印栈顶元素,然后查看右边。

          中序遍历:左->根->右   先入栈根节点,然后自顶向下入栈左孩子,直到不能入栈,打印当前节点,查看它是否有右孩子,如果有遍历右边。

           后续遍历:左->右->根   先入栈根节点,然后自顶向下入栈左孩子,直到不能入栈,打印当前节点, 查看它是否有右孩子,如果有遍历右边。只有没有右孩子或者当前的栈顶元素为右孩子(证明已经访问过右孩子)才能输出根。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值