您的位置:首页 > 理论基础 > 数据结构算法

数据结构之二叉树的线索化

2015-10-24 14:10 387 查看
线索二叉树
指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树

lchild
ltag data
rtag rchild
当ltag 为0 时指向该结点的做孩子,为1 时指向该结点的前驱

当rtag为0 时指向该结点的右孩子,为1时指向该结点的后继

线索化:二叉树以某种次序遍历使其变为线索二叉树的过程称为线索化,实质:是将二叉链表中的空指针改为指向前驱或后继的线索,由于前驱和后继的信息只有在遍历该二叉树时才能得到,所以线索化的过程就是在遍历的过程中修改空指针的过程
#include<stdio.h>
#include<malloc.h>

#define TRUE 1
#define FALSE 0
#define OK 1
#define EEROR

typedef int Status ;
typedef enum{Link,Thread}tag;//记录是指向前驱后继还是指向其子树,link代表指向其子树,thread代表指向其前驱或者后继

typedef struct treeNode{
tag lTag;//是否指向前驱
tag rTag;//是否指向后继
char data;//数据域
treeNode *lchild;
treeNode *rchild;
}treeNode,*Tree;

Tree pre;//全局变量,代表指向刚刚访问过的结点

void create(Tree *tree){
char ch ;
scanf("%c",&ch);//输入结点的数据
if(ch == '#'){//如果输入#,则为空树
*tree = NULL;
}
else{
*tree = (treeNode *)malloc(sizeof(treeNode));

(*tree)->data = ch;
create(&(*tree)->lchild);//创建左子树
if((*tree)->lchild){//如果有左子树,则设置标志 lTag为 link
(*tree)->lTag = Link;
}
create(&(*tree)->rchild);//创建右子树
if((*tree) -> rchild){
(*tree)->rTag = Link;
}
}
}

/*

中序遍历线索化
当此结点没有左孩子(或者没有右孩子)时,修改其指针,lchild指向上一结点,也就是前驱(修改rchild,使其指向后继)
*/

void threadTree(Tree tree){//把二叉树线索化:在遍历过程修改空指针的过程
if(tree){

threadTree(tree->lchild);

if(!tree->lchild){//如果当前结点没有左孩子,则修改lTag为thread,并把lchild指向上一结点
tree->lTag = Thread;
tree->lchild = pre;
}
if(!pre->rchild){//如果上一结点没有右孩子,则修改上一结点的rTag为thread,并把rchild指向当前结点
pre->rTag = Thread;
pre->rchild = tree;
}
pre = tree;//更换pre
threadTree(tree->rchild);
}
}

/*
给线索化后的二叉树添加上头结点,并使头结点的lchild指向二叉树的根,让二叉树遍历的第一个结点lchild指向头结点,最后一个结点的rchild指向头结点,头结点的rchild指向二叉树遍历的最后一个
结点。这样既可以从第一个结点起顺后继进行遍历,也可以从最后一个结点起顺前驱进行遍历

*/
Status addHeadNode(Tree tree,Tree *th){//th指向头结点,为二重指针
*th = (treeNode*)malloc(sizeof(treeNode));//为头结点分配内存空间
(*th)->lTag = Link;
(*th)->rTag = Thread;
(*th)->rchild = *th;//右指针回指

if(!tree){//如果二叉树为空树,则左指针回指
(*th)->lchild = (*th);
}

else{
pre = (*th);//使pre指向头结点
(*th)->lchild = tree;//头结点的lchild指向二叉树的根
threadTree(tree);//线索化,起始时,pre指向头结点,结束时指向最后一个结点,所以可以使二叉树遍历的一个结点的lchild指向该头结点
pre->rTag = Thread;
pre->rchild = (*th);//pre现在是指向二叉树的最后一个结点,所以把rchild指向第一个结点
(*th)->rchild = pre;//把头结点指向最后一个结点
}
return OK;
}

void inOrder(Tree tree){//遍历二叉树线索链表
Tree p;
p = tree->lchild;//指向根结点

while(p != tree){
while(p->lTag == Link){//循环至第一个结点
p = p->lchild;
}
printf("%c",p->data);

while(p->rTag == Thread && p->rchild != tree){//如果有后继,则打印其后继的值,否则移至其右子树
p = p->rchild;
printf("%c",p->data);
}

p = p ->rchild;
}
}

void main(){
Tree tree,th;
printf("请用前序输入一棵二叉树:");
create(&tree);

addHeadNode(tree,&th);
inOrder(th);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: