C语言 二叉树之线索二叉树

直接上代码!

(1)线索二叉树的存储结构

1 typedef enum{link,thread}pointertag;/*link==0表示指向左右孩子指针,thread==1表示指向前驱或后继的线索*/
2 typedef struct BiTNode{//二叉线索存储结点结构
3     char data;
4     struct BiTNode *lchild,*rchild;//左右孩子指针
5     pointertag ltag;//左右标志
6     pointertag rtag;
7 }BiTNode,*BiTree;
8 BiTNode *pre;  //全局变量,始终指向刚刚访问过的结点 

(2)构造线索二叉树

 1 BiTNode *CreateBiTree(BiTNode *T){
 2         /*分配存储空间*/
 3     T = (BiTNode *)malloc(sizeof(BiTNode));
 4     char ch;
 5     printf("先序法创建二叉树,#表示空:"); 
 6     scanf("%c",&ch);
 7     //如果输入为空,则二叉树是空树
 8     if(ch=='#'){
 9         T = NULL;
10     }else{
11         if(!T){
12             printf("分配存储空间失败!");
13             exit(OVERFLOW);
14         }
15         T->data = ch;//先输入根结点
16         T->ltag=link;
17         T->rtag=link;
18         T->lchild = CreateBiTree(T->lchild);//递归生成左子树
19         T->rchild = CreateBiTree(T->rchild);//递归生成右子树
20     }
21     return T;
22 }

(3)中序线索化二叉树

 1 void InorderThread(BiTree T){
 2     if(T){
 3         InorderThread(T->lchild);
 4         if(!T->lchild){
 5             T->ltag=thread;
 6             T->lchild=pre;/*当前结点没有左孩子,则当前结点的左孩子指向前驱结点,即左孩子指向前驱 */
 7         }
 8         if(!pre->rchild && pre!=NULL){
 9             pre->rtag=thread;
10             pre->rchild=T;/*前驱结点没有右孩子,则前驱结点的右孩子指向当前节点,即右孩子指向后继 */
11         }
12         pre=T;
13         InorderThread(T->rchild);
14     }
15 }

提示:后继结点的处理麻烦些,因为此时T结点的后继还没有访问到,因此只能对它的前趋加点pre的右指针rchild进行判断。

(4)添加一个头结点

 1 BiTNode *InorderHead(BiTNode *head,BiTNode *T){
 2     head=(BiTNode *)malloc(sizeof(BiTNode));
 3     head->ltag=link;
 4     head->rtag=thread;
 5     head->rchild=head;
 6     if(!T){
 7         head->lchild=head;
 8     }else{
 9         head->lchild=T;
10         
11         pre=head;
12         InorderThread(T);
13         pre->rtag=thread;
14         pre->rchild=head;
15         head->rchild=pre;
16     }
17     return head;
18 }

提示:和双向链表结构一样,添加一个头结点,该结点的data域为空,lchild域的指针指向二叉树的根节点,ltag=0;rchild指向按某种遍历二叉树的最后一个结点,rtag=1.另外,令该遍历产生序列的第一个结点的lchild域指针和最后一个结点的rchild域指针均指向头结点

(5)中序遍历二叉树

 

 1 //中序遍历线索二叉树 
 2 void InOrderTraverse(BiTNode *head){
 3     BiTNode *T = head->lchild;//T指向根节点
 4     while(T != head){//空树或遍历结束时
 5         while(T->ltag == link)
 6             T = T->lchild;
 7         printf("%c  ",T->data);
 8         while(T->rtag == thread && T->rchild != head){
 9             T = T->rchild;
10             printf("%c  ",T->data);
11         }
12         T = T->rchild;
13     }
14 }

 

(6)在中序线索二叉树上查找后继后前驱

 1 //在中序线索二叉树上查找后继
 2 BiTNode *InOrderPostNode(BiTNode *T){
 3     if(T->rtag==thread)return(T->rchild); 
 4     else{
 5         BiTNode *q=T->rchild;//找右子树最先访问的结点 
 6         while(T->ltag==link)q=q->lchild;
 7         return(q);
 8     }
 9 }
10 //在中序线索二叉树上查找前驱 
11 BiTNode *InOrderPreNode(BiTNode *T){
12     if(T->ltag==thread) return(T->lchild);
13     else{
14         BiTNode *q=T->lchild;//找左子树最后访问的结点 
15         while(q->rtag==link)q=q->rchild;
16         return(q);        
17     }
18 } 

 

 

 整体代码及演示:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #define OVERFLOW -1
  4 typedef enum{link,thread}pointertag;
  5 typedef struct BiTNode{
  6     char data;
  7     struct BiTNode *lchild,*rchild;
  8     pointertag ltag;
  9     pointertag rtag;
 10 }BiTNode,*BiTree;
 11 BiTNode *pre;
 12 BiTNode *CreateBiTree(BiTNode *T){
 13         /*分配存储空间*/
 14     T = (BiTNode *)malloc(sizeof(BiTNode));
 15     char ch;
 16     printf("先序法创建二叉树,#表示空:"); 
 17     scanf("%c",&ch);
 18     //如果输入为空,则二叉树是空树
 19     if(ch=='#'){
 20         T = NULL;
 21     }else{
 22         if(!T){
 23             printf("分配存储空间失败!");
 24             exit(OVERFLOW);
 25         }
 26         T->data = ch;//先输入根结点
 27         T->ltag=link;
 28         T->rtag=link;
 29         T->lchild = CreateBiTree(T->lchild);//递归生成左子树
 30         T->rchild = CreateBiTree(T->rchild);//递归生成右子树
 31     }
 32     return T;
 33 }
 34 //中序线索化 
 35 void InorderThread(BiTree T){
 36     if(T){
 37         InorderThread(T->lchild);
 38         if(!T->lchild){
 39             T->ltag=thread;
 40             T->lchild=pre;//当前结点没有左孩子,则当前结点的左孩子指向前驱结点,即左孩子指向前驱 
 41         }
 42         if(!pre->rchild && pre!=NULL){
 43             pre->rtag=thread;
 44             pre->rchild=T;//前驱结点没有右孩子,则前驱结点的右孩子指向当前节点,即右孩子指向后继 
 45         }
 46         pre=T;
 47         InorderThread(T->rchild);
 48     }
 49 }
 50 BiTNode *InorderHead(BiTNode *head,BiTNode *T){
 51     head=(BiTNode *)malloc(sizeof(BiTNode));
 52     head->ltag=link;
 53     head->rtag=thread;
 54     head->rchild=head;
 55     if(!T){
 56         head->lchild=head;
 57     }else{
 58         head->lchild=T;
 59         
 60         pre=head;
 61         InorderThread(T);
 62         pre->rtag=thread;
 63         pre->rchild=head;
 64         head->rchild=pre;
 65     }
 66     return head;
 67 }
 68 //中序遍历线索二叉树 
 69 void InOrderTraverse(BiTNode *head){
 70     BiTNode *T = head->lchild;
 71     while(T != head){
 72         while(T->ltag == link)
 73             T = T->lchild;
 74         printf("%c  ",T->data);
 75         while(T->rtag == thread && T->rchild != head){
 76             T = T->rchild;
 77             printf("%c  ",T->data);
 78         }
 79         T = T->rchild;
 80     }
 81 }
 82 //在中序线索二叉树上查找后继
 83 BiTNode *InOrderPostNode(BiTNode *T){
 84     if(T->rtag==thread)return(T->rchild); 
 85     else{
 86         BiTNode *q=T->rchild;//找右子树最先访问的结点 
 87         while(T->ltag==link)q=q->lchild;
 88         return(q);
 89     }
 90 }
 91 //在中序线索二叉树上查找前驱 
 92 BiTNode *InOrderPreNode(BiTNode *T){
 93     if(T->ltag==thread) return(T->lchild);
 94     else{
 95         BiTNode *q=T->lchild;//找左子树最后访问的结点 
 96         while(q->rtag==link)q=q->rchild;
 97         return(q);        
 98     }
 99 } 
100 int main(){
101     BiTNode *T;
102     T = CreateBiTree(T);
103     BiTNode *pHead;
104     pHead = InorderHead(pHead,T);
105     InOrderTraverse(pHead);
106     return 0;
107 }
线索二叉树

测试输入:abd#g###ce##fh###

输出:d  g  b  a  e  c  h  f

先序法输入的树为:

 

学习数据结构ing,欢迎交流!!

posted @ 2021-10-12 20:23  旺旺哈  阅读(242)  评论(0)    收藏  举报