数据结构-线索二叉树

线索二叉树

###为什么要有线索二叉树?
  比如单向链表因为无法快速获得前驱结点,所以有了双向链表。线索二叉树就是因为普通二叉树无法直接的到前驱结点和后继结点的信息且空间浪费严重的问题,所以发明了线索二叉树。

线索二叉树

  当一个树采用中序遍历的时候,正好每隔一个节点的左右可以存放两个指针,可以存放前驱和后继。将每一隔加点扩展为五个元素的结构,每个节点包括:数据域、左标签、右标签、左指针、右右指针。

  当ltag左标签为0时,指向该结点的左孩子结点,为1时指向该结点的前驱结点。

  当rtag右标签为0时,指向该结点的右孩子结点,为1时指向该结点的后继结点。

代码实现 (c实现)

#include <stdio>
#include <stdlib.h>

typedef char ElemType;
typedef enmu {Link,Thread} PointerTag; //线索存储为,Link{0}表示指向左右孩子的指针,Thread{1}表示前驱后继结点
typedef struct BiThrNode
{
	char data;
	BiThrNode *lchild,*rchild;
	PionterTag ltag.rtag;
}BiThrNode,*BiThrTree;
//创建一个二叉树,一般使用前序遍历创建
void CreateBiThrTree(BiThrTree *T)
{
	char c;
	scanf("%c",&c);
	if(' '==c)
	{
		*T=NULL;
	}
	else
	{
		*T=(BiThrTree *)malloc(sizeof(BiThrNode));
		(*T)->data=c;
		(*T)->ltag=Link;//先默认结点有左右孩子结点,再遍历结点,实现线索化
		(*T)->rtag=Link;
		
		//递归调用创建左右子树
		CreateBiThrTree(&(*T)->lchild);
		CreateBiThrTree(&(*T)->rchild);
	}
}

//使用中序遍历来线索化树 递归方式
//定义全局变量*pre*,时刻更新表示刚刚访问过的结点
BiThrTree pre;
void InThreading(BiThrTree T)
{
	if(T)
	{
		//递归遍历左子树
		InThreading(T->lchild);
		//处理结点
		if(!T->lchild) //如果当前结点的左孩子结点为空,则将其左标志*ltag*位转化为线索,左指针*lchild*指向刚刚访问的前驱结点*pre*
		{
			T->ltag=Thread;
			T->lchild=pre;
		}
		if(!pre->rchild)//要判断刚刚访问结点的右孩子是否为空,为空则将pre的右指针*rchild*指向当前结点
		{
			pre->rtag=Thread;
			pre->rchild=T;
		}
		pre=T;
		//递归遍历右子树
		InThreading(T->rchild);
	}
}
//定义头指针,并初始化pre
void InOrderThreading(BiThrTree *p,BiThrTree T)
{
	*p=(BiThrTree *)malloc(sizeof(BiThrNode));
	(*p)->ltag=Link;
	(*p)->rtag=Thread;
	(*p)->rchild=*p; //先把自己当作前驱结点
	if(!T)
	{
		p->lchild=*p;
	}
	else
	{
		(*p)->lchild=T;
		pre=p;
		InThreading(T);
		//将最后一个结点的右指针指向它的后继结点(头结点),头结点的前驱结点指向最后一个结点*pre*,形成链路。
		pre->rchild=*p;
		pre->rtag=Thread;
		(*p)->rchild=pre;
	}
}
//非递归方式遍历线索二叉树
void visit(char c)
{
	printf("%c",c);
}
void InOrderTraverse(BiThrTree T)
{
	BiThrTree p;
	P=T->lchild;
	while(p!=T)//当为空树或者线索化结束后 *p=T*
	{
		while(p->ltag==Link)
			{
				p=p->lchild;
			}
		visit(p->data);
		while(p->rtag==Thread && p->rchild !=T )
			{
				p=p->rchild;
				visit(p->data);
			}
			p=p->rchild;
	}	
}
int main()
{
	BiThrTree P,T = NULL;
	CreateBiThrTree(&T);
	InOrderThreading(&P,T);
	printf("中序遍历输出为:\n");
	InOrderTraverse(P); //P为头指针 T为根结点
	return 0;
}

线索二叉树实际应用

https://blog.csdn.net/Tangs_/article/details/83040502?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

  上文链接写到:当路由器使用CIDR,选择下一跳的时候,或者转发分组的时候,通常会用最长前缀匹配(最佳匹配)来得到路由表的一行数据,为了更加有效的查找最长前缀匹配,使用了一种层次的数据结构中,通常使用的数据结构为二叉线索。

3/11/2020 5:58:23 PM

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值