二叉树的遍历问题

递归算法

  • 先序遍历
// 递归先序遍历
Status PreOrderTraverse(BiTree T)  
{
	if (T==NULL)
	    return OK;
	printf("%d\n",T->data);
	PreOrderTraverse(T->lchild);
	PreOrderTraverse(T->rchild);
} 
  • 中序遍历
// 递归中序遍历
Status InOrderTraverse(BiTree T)  
{
	if (T==NULL)
	    return OK;
	InOrderTraverse(T->lchild);
	printf("%d\n",T->data);
	InOrderTraverse(T->rchild);
}
  • 后序遍历
// 递归后序遍历
Status LastOrderTraverse(BiTree T)  
{
	if (T==NULL)  // 递归出口,当前结点指向NULL
	    return OK;
	LastOrderTraverse(T->lchild);  // 递归遍历左子树
	LastOrderTraverse(T->rchild);  // 递归遍历右子树
	printf("%d\n",T->data);  // 遍历完左右子树后,访问当前结点
}

非递归实现(利用栈)

  • 先序遍历
// 先序非递归遍历二叉树
Status PreOrderTraverse(BiTree T)
{
	BiTree p;
	SqStack S;	
	InitStack(&S);
    Push(&S,T);  // 根结点入栈
	while (!StackEmpty(&S))  // 出栈即访问了结点,栈空即所有结点均已访问,退出循环
	{
		while (GetTop(&S,&p) && p)   // 栈顶的树指针为空,即根结点向左走所有结点都已入栈
		{
			printf("%d\n",p->data);   // 边入栈,边访问(先序遍历)
			Push(&S,p->lchild);   // 向左走到尽头,把左儿子一路压入栈
		} 
		Pop(&S,&p);  // 将空指针出栈
		if (!StackEmpty(&S))  // 这个判断用于所有结点均已遍历,不需要再压入右孩子(否则第二句push操作将使得栈永远不为空,无限循环)
		{
			Pop(&S,&p);  // 访问结点
			Push(&S,p->rchild);  // 让该结点右儿子入栈
        }
	return OK;	// 完成遍历
} 
  • 中序遍历(算法思想与先序遍历类似,仅仅是访问结点(printf("结点的值"))的时间不同)
Status InOrderTraverse(BiTree T)
{
	BiTree p;
	SqStack S;
	InitStack(&S);Push(&S,T);
	while (!StackEmpty(&S))
	{
		while (GetTop(&S,&p) && p) Push(&S,p->lchild);
		Pop(&S,&p);
		if (!StackEmpty(&S))
		{
			Pop(&S,&p);
			printf("%d\n",p->data);  // 中序遍历在出栈的时候访问结点的值
			Push(&S,p->rchild);
		} 
	}	
}
  • 后序遍历(多了一个判断上一个访问结点的if语句以及退出循环的条件判断)
Status PostOrderTraverse(BiTree T)
{
	BiTree p;
	BiTree pre=NULL;  // 记录上一个访问的结点指针
	SqStack S;	
	InitStack(&S);Push(&S,T);
	while (!StackEmpty(&S))
	{
		while (GetTop(&S,&p) && p) 
		{
			Push(&S,p->lchild);
		} 
		Pop(&S,&p);
		if (!StackEmpty(&S))
		{ 
			Pop(&S,&p);
			if (p->rchild==NULL || pre==p->rchild)  // 如果该结点右儿子是上一个访问的结点或者该结点没有右儿子
			{
				printf("%d\n",p->data);  // 访问该节点数据
				pre=p;  // 将该结点设置为上一个访问的结点
			}
			else
				Push(&S,p);	 // 右儿子还没被访问,不是访问该结点的时候,压回堆栈
	        Push(&S,p->rchild);
        }
		if (pre==T)  // 当访问的上一个结点为根结点,表明后序遍历结束,退出循环
		    break;	
	}	
} 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值