时构建线索二叉树的结构体
线索二叉树比平常的二叉树多了一个ltag域和一个rtag域,他们的作用在后面遍历时会说
#include<stdio.h>
#include<stdlib.h>
typedef char datatype;
typedef struct btnode {
datatype data;
btnode* lchild; //二叉树的左孩子指针域
btnode* rchild; //二叉树的右孩子指针域
int LTag,RTag; //左右Tag值
}btnode;
typedef struct binarytree {
btnode* root;
}binarytree;
进行二叉树的线索化之前先建立一颗二叉树
构造空树的函数:
void nulltree(binarytree* bt) {
bt->root = NULL;
}
建立一颗二叉树的函数;
btnode* newnode(btnode* node, datatype x) { //给结点赋值函数
node = (btnode*)malloc(sizeof(btnode));
node->data = x;
return node;
}
binarytree* maketree(binarytree* bt, datatype x, binarytree* lt, binarytree* rt) {
bt->root = newnode(bt->root, x); //给二叉树的根节点赋值
bt->root->lchild = lt->root;
bt->root->rchild = rt->root;
return bt;
}
main函数中建立一颗正常的二叉树bt1
int main() {
binarytree bt1, bt2, bt3, bt4, bt5;
nulltree(&bt5);
maketree(&bt4, 'D', &bt5, &bt5);
maketree(&bt3, 'C', &bt4, &bt5);
maketree(&bt2, 'B', &bt5, &bt5);
maketree(&bt1, 'A', &bt2, &bt3);
return 0;
}
现在进行二叉树的线索化,二叉树的线索化实质是二叉树的遍历。
左右tag域的作用:二叉树按照某种顺序遍历后得到的一个顺序结构,遍历后的结果中如果结点的左孩子为空,则把ltag置为1,同时该结点的lchild指向该结点的前驱,同理,结点的右孩子为空,则把rtag置为1,同时rchild指向该结点的的后继,若结点的左右孩子都不为空,则ltag=0,rtag=0,这里有两个特殊的结点,则是第一个结点和最后一个结点,若第一个结点的左孩子为空,则它的lchild可以指向一个NULL的前驱结点,若最后一个结点的右孩子为空,则它可以指向一个NULL的后继结点
例子:
bt1中序遍历结果为:BADC,B是遍历结果的第一个结点,B结点的左右孩子均为空,此时B结点有一个后继结点D,由于B结点是第一个结点,且B结点的左孩子为空,所以可以看作B结点也有一个前驱结点NULL结点,此时将B结点的ltag域置为1,同时B的lchild指针域指向NULL结点,B结点的rtag置为1,同时B的rchild指向他的后继结点A,A结点左右孩子均不为空,所以将A结点的左右tag值置为0,D结点的左右孩子均为空,遍历结果他有一个前驱结点A,所以他的ltag=1,lchild指向A结点,他还有一个后继结点C,所以他的rtag=1,rchild指向他的后继结点C,遍历结果的最后一个结点C左孩子不为空,但右孩子为空,所以他的ltag=0,rtag=1,rchild指向一个NULL的后继结点
以上的过程就是二叉树的线索化
btnode*pre=NULL; //设置一个全局变量pre
//pre意义为当前结点的前驱结点,p为当前结点
void inthread(btnode*p){
if(p){ //线索化左子树
inthread(p->lchild);
if(p->lchild==NULL){
p->LTag=1;
p->lchild=pre;
}
if(pre!=NULL&&pre->rchild==NULL){
pre->RTag=1;
pre->rchild=p;
}
pre=p; 把当前结点赋值给pre
inthread(p->rchild); //线索化右子树
}
}
void inthreadtree(binarytree*bt){ //二叉树的线索化函数
inthread(bt->root);
}
接下来是线索化二叉树的遍历:
void inordertree(binarytree*bt){
btnode*p=bt->root;
if(p){
while(p->lchild){ //遍历最左结点
p=p->lchild;
}
while(p->RTag==1){ //根据线索RTag访问后继结点直到访问到根节点
printf("%c",p->data);
p=p->rchild;
}
printf("%c",p->data); //访问根节点
while(p->rchild){
p=p->rchild;
}
while(p->lchild&&p->lchild!=bt->root){ //访问右子树的最右结点的最左结点
p=p->lchild;
}
while(p){
printf("%c",p->data);
p=p->rchild;
}
printf("\n");
}
}
main函数:
int main() {
binarytree bt1, bt2, bt3, bt4, bt5;
nulltree(&bt5);
maketree(&bt4, 'D', &bt5, &bt5);
maketree(&bt3, 'C', &bt4, &bt5);
maketree(&bt2, 'B', &bt5, &bt5);
maketree(&bt1, 'A', &bt2, &bt3);
inthreadtree(&bt1);
inordertree(&bt1);
return 0;
}
源码在此:https://blog.csdn.net/hypnumberone/article/details/124233555