线索二叉树的实现

时间:2021-08-27 17:33:43

<span style="font-size:18px;">/*
1.二叉树遍历算法提供了二叉树的一次性遍历,但是二叉树遍历算法无法实现用户程序像分步
遍历单链表那样分步遍历二叉树。线索二叉树就是专门为实现分步遍历二叉树而设计的。线索二叉树可以实现像双向
链表那样,既可以从前向后分步遍历二叉树,又可以从后向前分步遍历二叉树
2.当按某种规则遍历二叉树时,保存遍历时得到的节点的后继节点信息和前驱节点信息的最常用的方法是建立线索二叉树
3.线索二叉树的规定:当某节点的左指针为空时,令该节点指针指向按某种方法遍历二叉树时得到的该节点的前驱节点;当某节点的右指针
为空时,令该指针指向按某种方法遍历二叉树时得到该节点的后继节点
4.我们把节点中指向前驱和后继节点的指针称为线索,把在二叉树的节点上加上线索的二叉树称为线索二叉树,把对二叉树以某种方法(
如前序,中序,或后序方法)遍历使其变为线索二叉树的过程称按该方法对二叉树进行线索化。
5.线索二叉树的用途:一旦建立了某种方式的线索二叉树,用户程序就可以像操作双向链表一样操作该线索二叉树。
例如,一旦建立了中序线索二叉树,用户程序就可以设计一个正向循环结构遍历该二叉树的所有节点,循环初始定位在中序线索二叉树的第一个位置
,每次循环使指针指向当前节点的中序遍历的后继节点,当指针指向中序线索二叉树的最后一个节点位置后时,循环过程结束;
或者用户程序可以设计一个反向循环结构遍历该二叉树的所有结点,循环初始定位在中序线索二叉树的最后一个节点位置,每次循环使指针向当前
节点的中序遍历的前驱节点位置,当指针指向中序线索二叉树的第一个节点位置前时,循环结束。


*/
#include<stdio.h>
#include<malloc.h>
typedef char DataType;
//中序线索二叉树中节点的结构体
typedef struct Node{

DataType data;//数据域
int leftThread;//左线索
struct Node *leftChild;//左指针
struct Node *rightChild;//右指针
int rightThread;//右线索
}ThreadBiNode;//节点的结构体定义

typedef struct{

ThreadBiNode *root;//头指针
ThreadBiNode *current;//当前节点指针
int nextComplete;//遍历结束标志
}ThreadBiTree;




//进行中序线索化的函数
void InThread(ThreadBiNode *current,ThreadBiNode **pre){
//中序线索二叉树
//current为当前节点指针,pre为当前节点的中序前驱节点指针
if(current!=NULL){

InThread(current->leftChild,pre);//中序线索化左子树
if(current->leftChild==NULL){

current->leftThread=1;//建立线索标志
current->leftChild=*pre;//建立左线索指针
}else{
current->leftThread=0;//有左节点
}

if(current->rightChild!=NULL){

current->rightThread=0;//有右子树
}else{

current->rightThread=1;
}


if((*pre)->rightChild==NULL){

(*pre)->rightThread=1;//建立右线索标志
(*pre)->rightChild=current;//建立右线索指针
}else{

current->rightThread=0;//存在右子树
}
*pre=current;//前序节点指针等于当前节点指针
InThread(current->rightChild,pre);//中序化右子树

}
}

void CreatInThread(ThreadBiNode **root){

//创建中序线索化二叉树tree
ThreadBiNode *t=*root;//保存原二叉树根节点指针
ThreadBiNode *current,*pre=*root;
//建立头节点
*root=(ThreadBiNode *)malloc(sizeof(ThreadBiNode));
if(t==NULL){

(*root)->leftThread=0;
(*root)->rightThread=1;
(*root)->leftChild=*root;
(*root)->rightChild=*root;
printf("the root is null\n");
}else{
//当二叉树为非空

current=t;
(*root)->leftChild=t;//置头节点的左指针
(*root)->leftThread=0;//置头节点的左线索




InThread(current,&pre);//线索化二叉树

pre->rightChild=*root;//置最后一个节点的右指针
pre->rightThread=1;//置最后一个节点的右线索
(*root)->rightChild=pre;//置当前的右指针
(*root)->rightThread=1;//置头节点的右线索
}

}


void ThreadInitiate(ThreadBiTree *tree,ThreadBiNode *root){
//初始化中序线索二叉树函数
tree->root=root;
tree->current=root;
if(root=NULL){

tree->nextComplete=1;
}else{

tree->nextComplete=0;
}
}


void First(ThreadBiTree *tree){
//使中序线索二叉树tree的当前节点指针指向中序遍历的第一个节点
tree->current=tree->root;
while(tree->current->leftThread==0){

tree->current=tree->current->leftChild;
}

if(tree->current==tree->root){

tree->nextComplete=1;
}else{

tree->nextComplete=0;
}

}



void Next(ThreadBiTree *tree){
//使中序线索二叉树tree的当前节点指针指向中序遍历的下一个节点

ThreadBiNode *p=tree->current->rightChild;

if(tree->nextComplete==1){

return ;
}

if(tree->current->rightThread==0){

while(p->leftThread==0){

p=p->leftChild;

}
}


tree->current=p;
if(tree->current==tree->root){
tree->nextComplete=1;
}


}


int EndOfNext(ThreadBiTree *tree){
//判断是否已到中序线索二叉树tree的尾部
//nextComplete=1表示已到,否则未到
return tree->nextComplete;
}



ThreadBiNode *GetTreeNode(DataType item,ThreadBiNode *left,
ThreadBiNode *right){
//创建二叉树节点函数
ThreadBiNode *p;
p=(ThreadBiNode *)malloc(sizeof(ThreadBiNode));
p->data=item;
p->leftChild=left;
p->rightChild=right;
return p;
}



void MakeCharTree(ThreadBiNode **root){
//创建二叉树函数
ThreadBiNode *b,*c,*d,*e,*f,*g;
g=GetTreeNode('G',NULL,NULL);
d=GetTreeNode('D',NULL,g);
b=GetTreeNode('B',d,NULL);
e=GetTreeNode('E',NULL,NULL);
f=GetTreeNode('F',NULL,NULL);
c=GetTreeNode('C',e,f);
*root=GetTreeNode('A',b,c);
}



void main(){

ThreadBiNode *root;
ThreadBiTree tree;

MakeCharTree(&root);//构造二叉树

CreatInThread(&root);//创建中序线索二叉树
printf("二叉树中序正向遍历序列为:");
ThreadInitiate(&tree,root);//循环初始化
for(First(&tree);!EndOfNext(&tree);Next(&tree)){//循环遍历访问

printf("%c ",tree.current->data);
}

printf("\n");


}</span>


运行结果:

线索二叉树的实现