数据结构总结 第五章 二叉树——线索二叉树

//充分利用空链域来存放结点的前驱和后继信息
typedef struct BiThrNode
{
	TElemType data;
	struct BiThrNode *lchild, *rchild;
	int LTag, RTag;
}

/*
	lchild LTag data RTag rchild
*/

/*
	LTag=0,lchild指示结点的左孩子
	LTag=1,rchild指示结点的前驱

  	RTag=0,lchild指示结点的左孩子
	RTag=1,rchild指示结点的后继
*/

//中序遍历线索化
//线索化只是针对有空链域的结点,只有这样的结点才会有前驱或者后继或者二者都有
//中序遍历一定是先递归左子树,再操作,再递归右子树
void InThreading(BiThrTree p)
{
	if(p)
	{
		InThreading(p->lchild);

		//如果p的左孩子为空
		//因为是中序遍历(左中右),说明p有前驱
		if(!p->lchild)
		{
			p->LTag = 1;
			p->lchild = pre;
		}
		else	//因为是递归,所以会遇到有左孩子的结点,设置LTag为0
		{
			p->LTag = 0;
		}

		//如果p没有右孩子,那么p的右指针原先就会为空,线索化以后,p的右指针将会指向后继
		//但因为是中序遍历,递归完左子树后,才回到p,所以无法判断p的右孩子
		//那么递归完左子树后,pre就是左子树中序遍历的最后一个结点
		
		//如果p的前驱没有右孩子
		//那么前驱就有后继
		if(!pre->rchild)
		{
			pre->RTag = 1;
			pre->rchild = p;
		}
		else
		{
			pre->Rtag = 0;
		}
		
		//对于右子树来说,p就是右子树最开始的前驱
		pre = p;

		InThreading(p->rchild);
	}
}

//带头结点的二叉树中序线索化
void InOrderThreading(BiThrTree *Thrt, BiThrTree T)
{
	//建立头结点,头结点有左孩子,无右孩子
	//那么对于头结点来说,如果T非空,那么左孩子就为T
	//右孩子初始化为头结点,即自己是自己的后继
	*Thrt = new BiThrNode;
	(*Thrt)->LTag = 0;
	(*Thrt)->RTag = 1;
	(*Thrt)->rchild = *Thrt;

	if(!T)
	{
		//如果T为空树,那么头结点的前驱也指向自己,即自己是自己的左孩子
		(*Thrt)->lchild = Thrt;
	}
	else
	{
		//如果T非空,那么左孩子就为T
		(*Thrt)->lchild = T;
		//pre作为整个T的前驱
		pre = Thrt;

		InThreading(T);

		//中序线索化完以后,就到了中序遍历的最后一个结点
		//在对最后一个结点线索化可以确定最后一个结点一定没有右孩子,所以在pre赋值给p(即最后一个结点)后,不会进行右子树递归
		pre->rchild = *Thrt;
		pre->RTag = 1;
		*Thrt->rchild = pre;
		//头结点的后继是最后一个结点,最后一个节点的后继是头结点 = =
	}
}

//遍历中序线索二叉树,这里的T是带了头结点的
void InOrderTraverse_Thr(BiThrTree T)
{
	//带头结点的线索二叉树的左孩子指向真正的树
	p = T->lchild;

	while(p != T)
	{
		//沿左孩子向下,即找到中序遍历的第一个结点
		while(p->Ltag == 0)
		{
			p = p->lchild;
		}

		//访问其左子树为空的结点
		cout<<p->data;
		
		//沿线索访问后继结点,即中间结点
		while(p->RTag == 1 && p->rchild != T)
		{
			p = p->rchild;
			cout<<p->data;
		}

		//所以转向p的右子树,对右子树线索化遍历
		p = p->rchild;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值