数据结构16————二叉树的线索化

数据结构16————二叉树的线索化

一.内容

  1. 二叉树的线索化
  2. 线索二叉树的线索化
  3. 线索二叉树的简单应用

二.二叉树的线索化

1.二叉树的线索化的原因

当我们使用二叉链表实现二叉树,对空间会造成很大的浪费。当我们存储有n个节点的二叉树时,一共有2n个指针域,而二叉树一共有n-1个分支连线。即只有n-1个指针域指向节点,剩下的n+1都存的是空指针NULL。
为了提高空间的利用率,所以我们将原本存NULL的指针域存为其他有价值的信息(改节点的前驱和后继)

2.二叉树线索化的步骤

将原本存在存NULL的指针域存为该节点的前驱和后继。那么问题来了,前驱和后继指的是什么遍历序列的前驱和后继呢?答案是都可以,线索化分为3种,前序线索二叉树,中序线索二叉树,后序线索二叉树

我们以中序二叉树的线索化为例

  • 画出二叉树,写出二叉树的中序序列
  • 对于每个节点
    • 如果左子树为空,左指针连向它的前驱节点
    • 如果右子树为空,右指针连向它的后驱节点
      这里写图片描述

三.二叉树的线索化的代码实现

1.二叉树的结构设置

如果沿用之前的的二叉链表来实现的二叉线索树,就会存在一个问题,没法判断这个指针域,是原来二叉树的连线,还是线索化后的连线。为了解决上面这个问题我们就要增加一个标志域,来表示该指针是不是线索化后的指向。
这里写图片描述

2.二叉树的结构体代码
typedef enum {Link,Thread} PointerTag;//Link== 0 表示指向左右孩子的节点。
                                      //Therad == 1表示指向前驱或者后继
typedef char Elemtype;				
typedef struct BithrNode{ //二叉线索节点结构 
	Elemtype data;
	struct BithrNode *lchild,*rchild;//左右孩子指针
	PointerTag LTag; 
	PointerTag RTag; 
}BiThrNode,*BiThrTree;
3.二叉树线索化代码

可以很明显的看出二叉树的线索化,只是将中序遍历代码进行更改

void InThreading (BiThrTree root){
	if(root==NULL)
		return;

	InThreading(root->lchild);//递归左子树的线索化 
	if(root->lchild==NULL){
		root->LTag =Thread;
		root->lchild = p; // 左孩子指向前驱 
	} 
	if(p!=NULL&&p->rchild == NULL){
		p->RTag = Thread;
		p->rchild = root;//前驱指向根节点 
	} 
	p = root; // 更新前驱 
	InThreading(root->rchild);//递归右子树的线索化 
}

四.二叉线索化的应用

使用二叉线索树进行中序遍历
如果给定的二叉树中序线索树,要进行二叉树的中序遍历。就可以不使用二叉树中序遍历的代码,可以使用二叉中序线索树的特有遍历方法

思路:

  • 找到二叉中序序列的第一个节点
  • 根据节点的右子树指针和后驱指针来寻找下一个节点
  • 当遍历的最后一个节点是,右指针域为NULL
void InOrderTraverse_Thr(BiThrTree root){
	
	BiThrNode *p;
	p=root->lchild;// p为根的左孩子
	while(p!=NULL) // 空树或者遍历结束 p == T
	{
		while(p->LTag == Link) //找到中序序列的第一个节点 
			p = p ->lchild;
		printf("%c",p->data);
		while(p->RTag==Thread && p->rchild !=NULL){
			p = p->rchild;
			printf("%c",p->data);
		} 
		p= p->rchild; 	
		
	} 
}

五.参考资料

《大话数据结构》
《数据结构与算法》

六.源码地址

text13中

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值