线索化二叉树(中序便利解决)

线索:指向结点前驱和后继的指针

线索链表:加上线索二叉链表

线索二叉树:加上线索的二叉树(图形式样)

线索化:对二叉树以某种次序遍历使其变为线索二叉树的过程

1)若结点有左子树,则lchild指向其左孩子; 否则, lchild指向其直接前驱(即线索);

2)若结点有右子树,则rchild指向其右孩子; 否则, rchild指向其直接后继(即线索) 。 为了避免混淆,增加两个标志域

大致讲一下思维:

 

 

 这是我以中序的方式解决的,理解完这个代码,可以尝试以前序,后序试试,可加深印象

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


// 定义线索二叉树结构体
typedef struct Tree
{
	int data, Ltag, Rtag;			// 数据域及左右标记
	struct Tree *Lchild, *Rchild;	// 左右孩子指针
}Tree,*Trees;

Trees pre = NULL;

// 初始化二叉树,只设置根节点
void InitBiTree(Trees *boot)
{
	*boot = (Trees)malloc(sizeof(Tree));
	(*boot)->Lchild = (*boot)->Rchild = NULL;
	(*boot)->Ltag = (*boot)->Rtag = 0;
}

// 创建二叉树
void CreateBiTree(Trees &boot)
{
	int number;
	scanf("%d", &number);
	if (number == 0)
	{
		boot = NULL;
	}
	else
	{
		boot = (Trees)malloc(sizeof(Tree));
		boot->data = number;
		boot->Lchild = boot->Rchild = NULL;
		boot->Ltag = boot->Rtag = 0;
		CreateBiTree(boot->Lchild);
		CreateBiTree(boot->Rchild);
	}
}


// 添加线索
void InserLineTree(Trees &boot)
{
	if (boot != NULL)
	{
		InserLineTree(boot->Lchild);
		if (boot->Lchild == NULL)
		{
			boot->Ltag = 1;
			boot->Lchild = pre;		// 设置前驱
		}
		if (pre != NULL && pre->Rchild == NULL)
		{
			pre->Rchild = boot;
			pre->Rtag = 1;
		}
		pre = boot;	// 当前访问节点是下一个访问节点的前驱
		InserLineTree(boot->Rchild);	// 线索右子树
	}
}


// 创建头节点
Trees InorderThread(Trees &rt)
{
	Trees throot;
	if (!(throot = (Trees)malloc(sizeof(Tree))))
	{
		printf("创建头结点失败.\n\n");
		exit(1);
	}

	throot->Ltag = 0;			// 指向左子树
	throot->Rtag = 1;			// 指向前驱
	throot->Rchild = throot;	// 指向自己

	if (!throot)
	{
		throot->Lchild = throot;  // 如果二叉树为空,指针指向头节点
	}
	else
	{
		throot->Lchild = rt;		// 指向二叉树的根
		pre = throot;				// 指向头结点
		InserLineTree(rt);			// 添加线索
		pre->Rchild = throot;
		pre->Rtag = 1;
		throot->Rchild = pre;
	}
	return throot;
}

// 使用中序遍历查找节点前驱
void InPre(Trees boot)
{
	Trees q = NULL;
	if (boot->Ltag == 1)
	{
		pre = boot->Lchild;
	}
	else
	{
		for (q = boot->Lchild; q->Rtag == 0; q = q->Rchild)
		{
			pre = q;
		}
	}
	if (pre)
	{
		printf("中序遍历找到的前驱为:%d\n", pre->data);
	}
	else
	{
		printf("中序遍历没有找到前驱!\n");
	}
}


// 使用中序遍历查找节点后继
void InNext(Trees boot)
{
	Trees q = NULL;
	if (boot->Rtag == 1)
	{
		pre = boot->Rchild;
	}
	else
	{
		for (q = boot->Rchild; q->Ltag == 0; q = q->Lchild)
		{
			pre = q;
		}
	}
	if (pre)
	{
		printf("中序遍历找到的后继为:%d\n", pre->data);
	}
	else
	{
		printf("中序遍历没有找到后继!\n");
	}
}

// 查找线索二叉树上的第一个节点
Trees InFirst(Trees boot)
{
	Trees p = boot;
	if (!p)
	{
		return 0;
	}
	while (p->Ltag == 0)
	{
		p = p->Lchild;

	}
	return p;
}


// 中序遍历线索二叉树
void TinOrder(Trees &throot)
{
	Trees p;
	p = throot->Lchild;
	while (p != throot)
	{
		while (p->Ltag == 0)
		{
			p = p->Lchild;
		}
		printf("%d ", p->data);
		while (p->Rtag == 1 && p->Rchild != throot)
		{
			p = p->Rchild;
			printf("%d ", p->data);
		}
		p = p->Rchild;
	}
	printf("\n");
}



int main()
{
	Trees boot = NULL;
	printf("创建线索二叉树,当用户输入0结束操作!\n");
	CreateBiTree(boot);

	Trees throot;		// 头节点
	throot = InorderThread(boot);
	TinOrder(throot);	// 中序遍历
	InPre(boot);		// 中序查找前驱
	InNext(boot);		// 中序查找后继
	Trees bt = InFirst(boot);
	printf("中序遍历线索二叉树的第一个节点为:%d", bt->data);

	return 0;
}


非常欢迎大家能在讨论区指出此文的不足处,作者会及时对文章加以修正 !如果有任何问题,欢迎评论,非常乐意为您解答

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

XieZDev

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

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

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

打赏作者

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

抵扣说明:

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

余额充值