C语言解决二叉树的先序线索化、中序线索化和后序线索化

C语言解决二叉树的先序线索化、中序线索化和后序线索化

有如下的一个二叉树:
在这里插入图片描述
节点的结构为:

typedef struct BiTree {
	char val;	//节点的值
	struct BiTree* lchild;	//左孩子
	struct BiTree* rchild;	//右孩子
	int rtag;	//左孩子是否线索化,0表示未被线索化
	int ltag;	//右孩子是否线索化,0表示未被线索化
}BiTree;

在初始化节点时rtag和ltag都赋值为0

先序线索化

开始之前,我先讲讲如何在草稿纸上做好节点的线索化。首先,我们先将如上的二叉树按照先序遍历的顺序写出来:A B C E I J D F G H
接着结合图走;A节点度数为2,无需线索化;C节点左孩子为空,先序遍历顺序B节点在C节点的左边,那么C节点线索化左孩子指向B节点;依次类推,H节点线索化后左孩子指向G节点,右孩子指向空。

了解怎么先序线索化的后,先看代码:

BiTree* pre = NULL;
void preThread(BiTree* root) {	//先序线索化二叉树
	if (root != NULL) {
		Traverse(root);
		if (root->ltag == 0) {
			preThread(root->lchild);
		}
		preThread(root->rchild);
	}
}
void Traverse(BiTree* root) {	//进行操作
	if (root->lchild == NULL) {
		root->lchild = pre;
		root->ltag = 1;
	}
	if (pre != NULL && pre->rchild == NULL) {
		pre->rchild = root;
		pre->rtag = 1;
	}
	pre = root;
}

跟着代码的执行顺序走一遍:开始全局变量pre指向NULL,根节点A进入Traverse方法,A的左节点不为NULL同时pre为NULL,pre更新为A节点;
这里的if (root->ltag == 0) 语句我先不说其作用,此时root还是为A节点,A节点的ltag==0,则将A的左孩子即B节点进入递归即preThread(B),B节点再进入Traverse方法;结果与A节点一样并且pre更新为B,再次进入第三个preThread方法此时节点为C,C的左孩子为NULL,则会指向为pre即B,其ltag更新为1;Traverse(C )出来后,此时的C->lchild已经更新为B若是没有if (root->ltag == 0) ,则会preThread(C->lchild)即preThread(B),会出现反复横跳也就是死循环,因此这就是该语句if (root->ltag == 0)的作用

当root为I时,此时pre指向E,经过Traverse(I)后,I的左孩子指向E,pre更新为I,结束语句并指向preThread(E->rchild)即preThread(J),此时J的左孩子指向为I;注意此时pre为I,I的右孩子为NULL,执行

pre->rchild = root;
pre->rtag = 1;

也就是I的右孩子指向J,并更新rTag为1.
这就是大致程序指向的步骤。结果为
在这里插入图片描述

中序线索化

先序线索化明白的话那么中序线索化你一定也能够明白
中序遍历:C I E J B D A G F H
代码:

BiTree* pre = NULL;
void midThread(BiTree* root) {	//中序线索化二叉树
	if (root != NULL) {
		midThread(root->lchild);
		Traverse(root);
		midThread(root->rchild);
	}
}
void Traverse(BiTree* root) {	//进行操作
	if (root->lchild == NULL) {
		root->lchild = pre;
		root->ltag = 1;
	}
	if (pre != NULL && pre->rchild == NULL) {
		pre->rchild = root;
		pre->rtag = 1;
	}
	pre = root;
}

可以看到和先序线索化的代码差不多甚至还要更加简单点。没错,如果你明白了先序线索化,那么中序线索化你应该没有问题,要注意的就是中序递归的顺序
结果:
在这里插入图片描述

后序线索化

与中序线索化一样
后序遍历:I J E C D B G H F A

代码:

BiTree* pre = NULL;
void lastThread(BiTree* root) {	// 后序线索化二叉树
	if (root != NULL) {
		lastThread(root->lchild);
		lastThread(root->rchild);
		Traverse(root);
	}
}
void Traverse(BiTree* root) {
	if (root->lchild == NULL) {
		root->lchild = pre;
		root->ltag = 1;
	}
	if (pre != NULL && pre->rchild == NULL) {
		pre->rchild = root;
		pre->rtag = 1;
	}
	pre = root;
}

结果:
在这里插入图片描述

总结

欢迎指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值