线索二叉树的基本操作(C语言)

线索二叉树的基本概念

对于n个结点的二叉树,在二叉链存储结构中有n+1个空链域,利用这些空链域存放在某种遍历次序下该结点的前驱结点和后继结点的指针,这些指针称为线索,加上线索的二叉树称为线索二叉树

这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(Threaded BinaryTree)
在二叉树的结点上加上线索的二叉树称为线索二叉树,对二叉树以某种遍历方式(如先序、中序、后序或层次等)进行遍历,使其变为线索二叉树的过程称为对二叉树进行线索化。

来自百度百科,由“科普中国”科学百科词条编写与应用工作项目 审核 。

线索二叉树的基本操作

二叉树的结构定义

#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0

typedef char TElemType;

// Link(值为 0 )表示指向左右孩子指针,Thread(值为 1 )表示指向前驱或后继的指针
typedef enum {Link,Thread} PointerTag;

typedef struct BiThrNode {
	TElemType data;
	struct BiThrNode* lchild, * rchild;   //左右孩子指针
	PointerTag LTag, RTag;            //左右标志
}BiThrNode;
typedef struct BiThrNode* BiThrTree;

前序构造二叉链表

/* 前序构造二叉链表 */
int CreateBiThrTree(BiThrTree* T)
{
	TElemType e;
	scanf(" %c", &e);
	if (e == '#')
		*T = NULL;
	else
	{
		*T = (BiThrTree)malloc(sizeof(BiThrNode));
		if (!(*T))   //如果分配失败
			exit(-1);

		(*T)->data = e;
		CreateBiThrTree(&(*T)->lchild);
		if ((*T)->lchild)  //有左孩子
			(*T)->LTag = Link;
		CreateBiThrTree(&(*T)->rchild);
		if ((*T)->rchild)  //有右孩子
			(*T)->RTag = Link;
	}
	return OK;
}

中序遍历线索化

需定义一个 BiThrTree 类型的全局变量 pre,(用于)始终指向刚刚访问的结点

/* 中序遍历线索化 */
BiThrTree pre; //全局变量,(用于)始终指向刚刚访问的结点

void InThreading(BiThrTree p)
{
	if (p)
	{
		InThreading(p->lchild);
		if (!p->lchild)  //如果没有左孩子
		{
			p->LTag = Thread;  //前驱线索
			p->lchild = pre;  //左孩子指向前驱
		}
		if (!pre->rchild)  //如果前驱没有右孩子
		{
			pre->RTag = Thread;  //后继线索
			pre->rchild = p;  //前驱右孩子指针指向后继(当前结点p)
		}
		pre = p;   //保持 pre 始终指向 p 的前驱
		InThreading(p->rchild);
	}
}

中序遍历线索化,Thrt指向头结点

/* 中序遍历线索化,Thrt指向头结点 */
void InOrderThreadig(BiThrTree* Thrt, BiThrTree T)
{
	*Thrt = (BiThrTree)malloc(sizeof(BiThrNode));
	if (!(*Thrt))    //如果分配失败
		exit(-1);
	(*Thrt)->LTag = Link; //建立头结点
	(*Thrt)->RTag = Thread;
	(*Thrt)->rchild = (*Thrt);  //右指针回指
	if (!T)   //如果二叉树为空,左指针回指
		(*Thrt)->lchild = *Thrt;
	else
	{
		(*Thrt)->lchild = T;
		pre = (*Thrt);  //可以让下面中序遍历线索化时,中序序列的
		                //最左边的结点的lchild指向头结点
		InThreading(T);  //中序遍历线索化
		pre->rchild = *Thrt;  //最后一个结点指向一个头结点
		pre->RTag = Thread; //最后一个结点线索
		(*Thrt)->rchild = pre;
	}
}

(非递归法)中序遍历二叉线索树T(带头结点)

/* (非递归法)中序遍历二叉线索树T(头结点) */
void InOrderTraverse_Thr(BiThrTree T)
{
	BiThrTree p;
	p = T->lchild;      //p指向根结点
	while (p != T)       //空树或遍历结束
	{
		while (p->LTag == Link)
			p = p->lchild;
		printf("%c\n", p->data);
		while (p->RTag == Thread && p->rchild != T)
		{
			p = p->rchild;      //访问后继结点
			printf("%c\n", p->data);
		}
		p = p->rchild;        //进入右子树
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mirror_zz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值