线索二叉树
可学习的博客:
http://blog.csdn.net/m6830098/article/details/8707814
http://book.51cto.com/art/200907/134532.htm
http://www.lxway.com/6084102.htm
http://www.ihypo.net/854.html
https://pjf.name/post-127.html
实现代码:
1 //线索二叉树,这里在二叉树的基础上添加了线索化 2 #include <stdio.h> 3 #include <stdlib.h> 4 typedef char ElemType; 5 typedef enum {Link,Thread} childTag; //Link表示结点,Thread表示线索 6 typedef struct bitNode 7 { 8 ElemType data; 9 struct bitNode *lchild, *rchild; 10 int ltag, rtag; 11 } bitNode, *bitTree; 12 13 bitTree pre; //创建全局变量,表示刚刚访问过的结点 14 15 16 17 /* 18 创建二叉树,其输入必须按照前序遍历的次序。 19 T:二叉树根节点 20 arr:按照前序遍历次序排列的各节点的值。无孩子结点时用空格代替 21 */ 22 void create_tree(bitTree *T, char **arr) 23 { 24 char c; 25 sscanf(*arr,"%c",&c); //读入一个结点值 26 (*arr)++; 27 if(' '== c) //如果是空格,表示空结点 28 { 29 *T=NULL; 30 } 31 else 32 { 33 *T=(bitTree)malloc(sizeof(bitNode)); //构造新结点 34 (*T)->data=c; 35 (*T)->ltag=Link; 36 (*T)->rtag=Link; 37 create_tree(&(*T)->lchild,arr); //构造新结点的左孩子 38 create_tree(&(*T)->rchild,arr); //构造新结点的右孩子 39 } 40 } 41 42 43 /* 44 访问结点信息 45 */ 46 void visit(bitTree T) 47 { 48 printf("| %d | %c | %d |\n",T->ltag,T->data,T->rtag); 49 } 50 51 52 /* 53 前序遍历访问二叉树 54 */ 55 void pre_order_traverse(bitTree T,int level) 56 { 57 if(T) 58 { 59 visit(T); 60 pre_order_traverse(T->lchild,level+1); 61 pre_order_traverse(T->rchild,level+1); 62 } 63 } 64 65 /* 66 中序遍历二叉树,对其进行线索化 67 */ 68 void in_order_threading(bitTree T) 69 { 70 if(T) 71 { 72 in_order_threading(T->lchild); //左孩子线索化 73 if(!T->lchild) //如果左孩子为空,则将其指向直接前驱 74 { 75 T->lchild=pre; 76 T->ltag=Thread; 77 } 78 if(!pre->rchild) //如果上一个结点的右孩子为空,则将其指向直接后继。(注意:只有访问到下一个结点时,才会知道本结点的后继是谁) 79 { 80 pre->rchild=T; 81 pre->rtag=Thread; 82 } 83 pre=T; 84 in_order_threading(T->rchild); //右孩子线索化 85 } 86 } 87 88 /* 89 加入一个头结点,使二叉线索树成一个封闭环 90 P:带有头结点的二叉树。头结点的左孩子指向二叉树T;右孩子指向T树中的最后一个叶子结点 91 T:不带有头结点的二叉树。 92 */ 93 void in_thread(bitTree *P,bitTree T) 94 { 95 (*P)=(bitTree)malloc(sizeof(bitNode)); //构造新加入的头结点 96 (*P)->ltag=Link; 97 (*P)->rtag=Thread; 98 (*P)->rchild=*P; 99 if(!T) //如果二叉树为空,则P的孩子指向自己。 100 { 101 (*P)->lchild=*P; 102 } 103 else 104 { 105 (*P)->lchild=T; 106 pre=*P; 107 in_order_threading(T); //对二叉树进行线索化 108 (*P)->rchild=pre; //将头结点右孩子指向最后一个叶子结点 109 pre->rtag=Thread; //将最后一个叶子结点的右孩子指向头结点。这样,环就形成了。 110 pre->rchild=*P; 111 } 112 } 113 114 /* 115 非递归方式:中序遍历二叉树(树必须带有头结点,且已经线索化) 116 P:带有头结点的二叉树 117 */ 118 void in_order_traverse(bitTree P) 119 { 120 bitTree T; 121 T=P->lchild; 122 while(T!=P) //判断是否空树 123 { 124 while(T->ltag==Link) //从左孩子开始,直到叶子结点 125 { 126 T=T->lchild; 127 } 128 visit(T); 129 while(T->rtag==Thread && T->rchild!=P) //根据线索,访问后继结点。并且后继结点不是指向头结点的 130 { 131 T=T->rchild; 132 visit(T); 133 } 134 T=T->rchild; 135 } 136 } 137 138 139 int main() 140 { 141 bitTree P,T; 142 int level =1; //表示该结点的深度 143 char *arr="ab d ce "; //构造二叉树所需结点(按前序遍历方式输入) 144 create_tree(&T,&arr); //构造二叉树 145 printf("pre_order_traverse:先序遍历:\n"); 146 pre_order_traverse(T,level); //前序遍历输出二叉树 147 printf("in_order_traverse:中序遍历:\n"); 148 in_thread(&P,T); //二叉树线索化 149 in_order_traverse(P); //输出线索化后的二叉树 150 return 0; 151 }