有如下的一个二叉树:
节点的结构为:
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;
}
结果:
总结
欢迎指正