线索二叉树的结构
#define link 0
#define thread 1
//线索二叉树的结构
typedef enum flag{link,thread};
typedef struct BiNode{
int data;
BiNode *lchild,*rchild;//左右孩子指针
flag ltag,rtag;//左右标志
}BiNode,*BiTree;
线索二叉树的填充
ltag为0时,指向左孩子,为1时指向前驱
rtag为0时,指向右孩子,为1时指向后继
void inThreading(BiNode b,BiTree &pre){
//大判断条件 当前节点不为空
if(b){
inThreading(b->lchild,pre);//左子树线索化
if(b->lchild==NULL){//当前节点的左孩子为空
b->ltag=thread;
b->lchild=pre;
}else{
b->ltag=link;
}
if(pre->rchild==NULL){//前驱节点的右孩子为空
pre->rtag=thread;
pre->rchild=b;
}else{
pre->rtag=link;
}
pre=b;
inThreading(T->rchild,pre);//右子树线索化
}
}
H为根节点,G为最后一个节点。
加上头结点 遍历线索二叉树
加上线索的二叉树结构是一个双向链表结构,为了便于遍历线索二叉树,我们为其添加一个头结点,头结点左孩子指向原二叉树的根结点,右孩子指针指向中序遍历的最后一个结点。同时,将第一个结点左孩子指针指向头结点,最后一个结点的右孩子指针指向头结点。
线索二叉树添加头结点后如图所示:
带有头结点的线索二叉树遍历代码如下:
//T指向带头节点,头结点的lchild指针指向二叉树的根节点
//带头节点凑成了一个双向循环链表
void inOrderTraversePrint(BiTree b){
BiNode *p = T->lchild;//p指向根节点
while(p!=b){//b不为空 且没有遍历结束
//先找到第一个节点
while(p->ltag==link){
p=p->lchild;
} //现在p指向的是第一个节点
printf("%d",p->data);
while(p->rtag==thread&&p->rchild!=b){
p=p->rchild;
printf("%d",p->data);
}
//当p所指结点的rchild指向的是孩子结点而不是线索时,
//p的后继应该是其右子树的最左下的结点,即遍历其右子树时访问的第一个节点
p=p->rchild;
}
printf("\n");
}