线索二叉树的实现

来源:互联网 发布:java检测内存泄露 编辑:程序博客网 时间:2024/04/29 18:11

<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){//创建中序线索化二叉树treeThreadBiNode *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>


运行结果:


0 0