中序线索二叉树(C语言实现)

目录

1.线索二叉树的定义:

2.线索二叉树的存储结构:

3.创建中序线索二叉树

4.遍历中序线索二叉树

5.在中序线索二叉树上查找任意结点的中序前驱结点

6.在中序线索二叉树上查找任意结点的中序后继结点

7.在中序线索二叉树上查找值为x的结点  (实质为遍历) 


1.线索二叉树的定义:

        为了保留结点在某种遍历序列中直接前驱结点和直接后继结点的位置信息。可以利用二叉树的二叉链表存储结构中的空指针域来指示。这些指向直接前驱结点和直接后继结点的指针被称为线索。加了线索的二叉树称为线索二叉树。

2.线索二叉树的存储结构:

        标记域:用来识别指针域内存放的是指针还是线索(即存放的是左右孩子,还是前驱后继)

标记域为0则存储孩子,为1则存储线索。

typedef char ElemType;

typedef struct node
{
	ElemType data;       //数据域
	int ltag,rtag;           //标记域可以为char类型,占的空间较小
	struct node *left,*right;      //指针域
}BiTree;

3.创建中序线索二叉树

        1.首先申请头结点,建立头结点跟根结点的关系(头结点的左指针指向根结点,右指针先指向自己(最后指向最后一个结点));

        2.找到中序遍历的第一个结点(使其左指针指向头结点);

        3.对二叉树线索化(在遍历过程中加线索);

        4.建立最后一个结点和头结点的关系(即最后一个结点右指针指向头结点)

BiTree *ThrtBiTree(BiTree *t)
{
	BiTree *p,*pre,*thrt,*s[N];
	int top=0;
	thrt=(BiTree *)malloc(sizeof(BiTree));      //开辟头结点 
	thrt->ltag=0;thrt->rtag=1;     //设置头结点的标记域 
	thrt->right=thrt;        //头结点右指针指向自己
	if(t==NULL)              //根结点为空,头结点左指针域指向自己  
	{
		thrt->left=thrt;
	}
	else
	{
		thrt->left=t;                  //根结点左指针指向根结点
		pre=thrt;                      //前驱指针指向头结点
		p=t;                           //后继指针指向根结点
		do{
			while(p!=NULL)             //入栈向左走
			{
				s[top]=p;
				top++;
				p=p->left;
			}
			if(top>0)                 //栈非空出队
			{
				top--;
				p=s[top];
				if(p->left==NULL)       //加左线索 
				{
					p->left=pre;
					p->ltag=1;
				}
				if(pre->right==NULL)   //加右线索 
				{
					pre->right=p;
					pre->rtag=1;
				}
				pre=p;          //指针跟进 
				p=p->right;
			}

		}while(p!=NULL||top>0);       //后继指针指向空,并栈空循环结束
		pre->right=thrt;      //最后结点右指针指向头结点 
		pre->rtag=1;
		thrt->right=pre;     //头结点右指针指向最后一个结点 
	}
	return thrt;	  //返回头结点
}

4.遍历中序线索二叉树

        线索二叉树中隐含后继或前驱,故可先找到第一个结点(某种遍历时),顺着后继线索遍历;或找到最后一个结点,顺着前驱线索遍历。

void InOrderthrt(BiTree *thrt)
{
	BiTree *p;
	p=thrt->left;      //从根结点出发 
	while(p!=thrt)       //指向头结点时循环结束,即算法结束
	{
		while(p->ltag==0)
		{
			p=p->left;      //向左走到第一个结点 
		}
		printf("%d\t%c\t%d\t",p->ltag,p->data,p->rtag);
		while(p->rtag==1&&p->right!=thrt)       //判断有没有后继线索且是否指向头结点 
		{
			p=p->right;
			printf("%d\t%c\t%d\t",p->ltag,p->data,p->rtag);
		}
		p=p->right;     //否则向右走 
	}
} 

5.在中序线索二叉树上查找任意结点的中序前驱结点

        若此结点有左线索则左指针指向前驱结点,若无前驱线索,则其左孩子为根结点的最右边的结点为前驱结点。

BiTree *InPreNode(BiTree *p)   //查找P结点的中序前驱结点 
{
	BiTree *pre;
	pre=p->left;        //先指向其左孩子
	if(p->ltag!=1)    //判断此结点是否有左孩子 
	{
		while(pre->rtag==0)  //则沿着其左子树深入到最右边 
		{
			pre=pre->right;
		}
	}
	return pre;      //返回前驱结点
}

6.在中序线索二叉树上查找任意结点的中序后继结点

        若此结点有右线索则右指针指向后继结点,若无后继线索,则其右孩子为根结点的最左边的结点为后继结点。

BiTree *InPostNode(BiTree *p)   查找P结点的中序后继结点
{
	BiTree *post;
	post=p->right;     //先指向其右孩子
	if(p->rtag!=1)    //判断此结点是否有右孩子
	{
		while(post->ltag==0)
		{
			post=post->left;   //沿着此结点的右子树深入到最左边 
		}
	}
	return post;          //返回后继结点
}

7.在中序线索二叉树上查找值为x的结点  (实质为遍历) 

        线索二叉树求前驱,后继结点的操作可遍历整个树,故可先找到第一个结点(某种遍历时),顺着求后继算法遍历;或找到最后一个结点(某种遍历时),顺着求前驱算法遍历。

BiTree *Search(BiTree *head,ElemType x)   //在线索二叉树head中查找数据域为x的结点
{
	BiTree *p;
	p=head->left;    //指向根结点
	while(p->ltag==0&&p!=head) //寻找中序遍历的第一个结点 
	{
		p=p->left;
	}
	while(p!=head&&p->data!=x)
	{
		p=InPostNode(p);           //调用在中序线索二叉树上寻找p结点的后继结点操作,实现遍历效果 
	}
	if(p==head)             //p指向头结点说明未找到
	{
		printf("Not find the data!\n");
		return 0;
	}
	else
	{
		return p;		
	}
} 

以上内容均属于自己学习总结,若有错误,请指正,转载请注明出处

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值