线索二叉树及若干操做

 1 /* 遍历二叉树就是以必定的规则将二叉树中的节点排列成一个线性  2  * 序列,从而获得二叉树节点的各类遍历序列,其实质是:对一个  3  * 非线性的结构进行线性化。使得在这个访问序列中每个节点都  4  * 有一个直接前驱和直接后继。  5  * 传统的链式结构只能体现一种父子关系,¥不能直接获得节点在  6  * 遍历中的前驱和后继¥,而咱们知道二叉链表表示的二叉树中有  7  * 大量的空指针,当使用这些空的指针存放指向节点的前驱和后继  8  * 的指针时,则能够更加方便的运用二叉树的某些操做。  9  * 引入线索二叉树的目的是: 为了加快查找节点的前驱和后继。  10  *  11  * 对二叉树的线索化就是对二叉树进行一次遍历,在遍历的过程当中  12  * 检测节点的左右指针是否为空,若是是空,则将他们改成指向前  13  * 驱和后继节点的线索。  14  * */
 15 #include<stdio.h>
 16 #include<stdlib.h>
 17 
 18 #define OK 1
 19 #define ERROR 0
 20 
 21 typedef char ElemType;  22 typedef int Status;  23 
 24 /* 定义枚举类型,其值只能是Link和Thread  25  * Link表示的该指针指示的是孩子  26  * Thread表示的是还指针指示的是前驱或者是后缀  27  * */
 28 typedef enum {  29  Link,Thread  30 }PointerTag;  31 
 32 typedef struct ThrBiTrNode{  33  ElemType data;  34     struct ThrBiTrNode *lchild, *rchild;  35  PointerTag rTag, lTag;  36 }ThrBiTrNode, *ThrBiTree;  37 
 38 ThrBiTree Pre;  39 
 40 Status InitThreadBinaryTree(ThrBiTree* T){  41     *T = NULL;  42     return OK;  43 }  44 //先序创建二叉树,lchild和rchild都是指示作孩子和右孩子,因此lTag和rTag为Link
 45 Status ThreadBinaryTree_PreOrderInput(ThrBiTree* T){  46  ElemType c;  47     scanf("%c", &c);  48     if( ' ' == c ){  49         *T = NULL;  50  }  51     else{  52         *T = (ThrBiTrNode*)malloc(sizeof(ThrBiTrNode));  53         if( !*T ){  54             return ERROR;  55  }  56         (*T)->data = c;  57         (*T)->lTag = Link;  58         (*T)->rTag = Link;  59         ThreadBinaryTree_PreOrderInput(&(*T)->lchild);  60         ThreadBinaryTree_PreOrderInput(&(*T)->rchild);  61  }  62     return OK;  63 }  64 //<<中序遍历>>对二叉树进行<<线索化>>,可是没有提供Pre的初始值,只是给出了  65 //中间的过程,递归的思想和思考方式。  66 //1 线索化左子树  67 //2 对双亲节点处理//递归中的base  68 //3 线索化右子树
 69 Status InOrderThread(ThrBiTree T){  70     if( T != NULL ){  71         InOrderThread(T->lchild);        //线索化左子树  72         
 73         //对双亲节点进行线索化处理
 74         if( T->lchild == NULL ){    //若是左孩子为空,则将lchild做为索引  75                         //Pre指向刚刚访问的节点
 76             T->lTag = Thread;  77             T->lchild = Pre;  78  }  79         if( Pre->rchild == NULL ){    //直到如今才知道Pre的后缀是T,因此  80                         //要对Pre进行设置,若是Pre的rchild为空  81                         //则将Pre的rchild设置为后缀,指向T
 82             Pre->rTag = Thread;  83             Pre->rchild = T;  84  }  85 
 86         Pre = T;            //标记当前的节点称为刚刚访问过的节点  87                         //Pre最后会指向树的中序遍历的最后的  88                         //一个节点
 89 
 90         InOrderThread(T->rchild);    //线索化右子树
 91  }  92     return OK;  93 }  94 //建立中序线索二叉树,为上个函数提供Pre
 95 Status CreateInOrderThreadBinaryTree(ThrBiTree T, ThrBiTree* headOfTree){  96     *headOfTree = (ThrBiTrNode*)malloc(sizeof(struct ThrBiTrNode));  97     if( !headOfTree )  98         return ERROR;  99     (*headOfTree)->lTag = Link;        //将要指向T
100     (*headOfTree)->rTag = Thread;        //将头节点的rchild用于索引
101     (*headOfTree)->rchild = *headOfTree;       //指向自身
102     if( T == NULL ){ 103         (*headOfTree)->lchild = *headOfTree;    //若T为空树,则头节点的lchild 104                             //指向自身
105  } 106     else{ 107         (*headOfTree)->lchild = T; 108         Pre = *headOfTree;            //赋值了全局变量Pre
109         InOrderThread(T);                //中序线索化 110         //printf("\n%c\n",Pre->data); 111                         //执行完InOrderThread以后Pre指向最后 112                         //一个节点
113         Pre->rTag = Thread; 114         Pre->rchild = *headOfTree; 115         //(*headOfTree)->rchild = Pre;
116  } 117     return OK; 118 } 119 //对中序线索化后的线索二叉树使用<<非递归>>的代码进行中序遍历 120 //而且原来的递归形式的代码在这里是再也不能够进行遍历。 121 // 若是二叉树没有被线索化,也是使用<<非递归>>的代码进行遍 122 // 历的,可是那就须要借助于<<栈>>,可是在线索化以后,对线索 123 // 化的二叉树进行<<非递归>>的遍历就再也不须要栈的辅助。
124 Status visit(ElemType c){ 125     printf("%c ", c); 126     return OK; 127 } 128 Status InOrderTeaverse_NoRecursion(ThrBiTree T, ThrBiTree headOfTree){ 129 //headOfTree是T的头节点的指针,headOfTree->lchild = T;
130     while( T != headOfTree ){ 131         while( T->lTag == Link ){    //找到树(子树)的最左节点 132                         //用while接替if//
133                         //用if理解while// 134             T = T->lchild; 135  } 136         visit(T->data); 137 
138         while( T->rTag == Thread && T->rchild != headOfTree){ 139                         //这个while和下面的T=T->rchild 140                         //可用ifelse语句理解。 141                         //if(rchild是线索 && 不是最后一个节点) 142                         //else(rchild不是线索)-->走到右孩子 143                         //也就是代码T=T->rchild
144             T = T->rchild; 145             visit(T->data); 146  } 147         T = T->rchild; 148  } 149     return OK; 150 } 151 //求中序线索二叉树中中序序列下的第一个节点
152 ThrBiTrNode* SeekFirstNode_InOrderThrBiTree(ThrBiTree T){ 153     if( T != NULL ){ 154         while( T->lTag == Link ){ 155             T = T->lchild; 156  } 157         return T; 158  } 159     return ERROR; 160 } 161 //求中序线索二叉树中节点P在中序序列下的下一个节点
162 ThrBiTrNode* GetNextNode(ThrBiTrNode* CurrentP){ 163     if( CurrentP->rTag == Link ){    //有右孩子的时候,那么下一个就是以 164                     //右孩子为root的树的最左下角元素。 165                     //即seekFirstNode的返回值。
166         return SeekFirstNode_InOrderThrBiTree(CurrentP->rchild); 167  } 168     else{                //没有右孩子,则rchild指向后缀
169         return CurrentP->rchild; 170  } 171 } 172 //使用上面两个函数,SeekFirstNode_InOrderThrBiTree和GetNextNode来实现对 173 //中序先作二叉树的遍历
174 Status InOrderTraverse_NoRecursion_Method(ThrBiTree T, ThrBiTree head){ 175     for( T = SeekFirstNode_InOrderThrBiTree(T) ; T != head ; T = GetNextNode(T) ) 176         visit(T->data); 177     return OK; 178 } 179 
180 //test
181 /* ShowThread函数的目的是想在将T中序线索化以后,使用函数InOrderTraverse 182  * 函数中序遍历,输出一下节点中的信息以检验线索化,可是失败。缘由是:在 183  * 线索化以后,空指针域都被应用,全部InOrderTraverse函数中的if( T )是满 184  * 足不了的,故失败。 185 Status ShowThread(ThrBiTree C){ 186  printf("%d %d %d %d\n",(C->lchild)->data,(C->rchild)->data,C->lTag,C->rTag); 187  printf("%d %d\n",C->lTag,C->rTag); 188  return OK; 189  * */
190 
191 //中序遍历二叉树
192 Status InOrderTraverse(ThrBiTree T){ 193     if( T ){ 194         InOrderTraverse(T->lchild); 195         visit(T->data); 196         InOrderTraverse(T->rchild); 197  } 198     return OK; 199 } 200 int main(){ 201     ThrBiTree T,R,Head = NULL; 202     InitThreadBinaryTree(&T); 203 
204     printf("Please Input Binary Tree By PreOrder\n "); 205     ThreadBinaryTree_PreOrderInput(&T); 206 
207     printf(" InOrder Traverse before Thread with Recursion\n"); 208  InOrderTraverse(T); 209     printf("\n"); 210 
211     CreateInOrderThreadBinaryTree(T,&Head); 212     printf(" InOrder Traverse after Thread with no-Recursion\n"); 213  InOrderTeaverse_NoRecursion(T,Head); 214     printf("\n"); 215 
216     printf("The root is %c \n", T->data);    //不可以经过指针形参的值改变指针实参的值 217                         //或者说,对指针形参的改变不会做用到指针 218                         //实参上。
219 
220     ThrBiTrNode *firstOfInOrder = NULL,*secondOfInOrder = NULL; 221     if( SeekFirstNode_InOrderThrBiTree(T) != ERROR ){ 222         firstOfInOrder = SeekFirstNode_InOrderThrBiTree(T); 223         printf("the value of First Node of InOrderThreadBinaryTree is %c\n", firstOfInOrder->data); 224  } 225     secondOfInOrder = GetNextNode(firstOfInOrder); 226     printf("the value of Node after D is: %c \n", secondOfInOrder->data); 227     secondOfInOrder = GetNextNode(secondOfInOrder); 228     printf("the value of Node after B is: %c \n", secondOfInOrder->data); 229     secondOfInOrder = GetNextNode(secondOfInOrder); 230     printf("the value of Node after E is: %c \n", secondOfInOrder->data); 231     secondOfInOrder = GetNextNode(secondOfInOrder); 232     printf("the value of Node after A is: %c \n", secondOfInOrder->data); 233     secondOfInOrder = GetNextNode(secondOfInOrder); 234     printf("the value of Node after C is: %c \n", secondOfInOrder->data); 235     secondOfInOrder = GetNextNode(secondOfInOrder); 236     printf("the value of Node after G is: %c \n", secondOfInOrder->data); 237     secondOfInOrder = GetNextNode(secondOfInOrder); 238     printf("the value of Node after root is: %c \n", secondOfInOrder->data); 239 
240     printf(" InOrder Traverse after Thread with no-Recursion Method_2\n"); 241  InOrderTraverse_NoRecursion_Method(T,Head); 242 
243     return 0; 244 }
相关文章
相关标签/搜索