码迷,mamicode.com
首页 > 其他好文 > 详细

3.1 层次关系结构:树(2)

时间:2016-07-19 09:10:40      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:

3.3 c

  1 #include <stdio.h> 
  2 #include <stdlib.h> 
  3 #define QUEUE_MAXSIZE 50
  4 typedef char DATA;       //定义元素类型 
  5 typedef enum 
  6 {
  7     SubTree,
  8     Thread
  9 }NodeFlag;  //枚举值SubTree(子树)和Thread(线索)分别为0,1
 10 typedef struct ThreadTree  //定义线索二叉树结点类型 
 11 {
 12     DATA data;    //元素数据
 13     NodeFlag lflag; //左标志 
 14     NodeFlag rflag; //右标志 
 15     struct ThreadTree *left;    //左子树结点指针
 16     struct ThreadTree *right;    //右子树结点指针
 17 }ThreadBinTree;
 18 
 19 ThreadBinTree *Previous=NULL;     //前驱结点指针 
 20 
 21 ThreadBinTree *BinTreeInit(ThreadBinTree *node) //初始化二叉树根结点 
 22 {
 23      if(node!=NULL) //若二叉树根结点不为空 
 24          return node;
 25      else
 26          return NULL;
 27 }
 28 int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n) //添加数据到二叉树 
 29 //bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树 
 30 {
 31     if(bt==NULL)
 32     {
 33         printf("父结点不存在,请先设置父结点!\n");
 34         return 0;
 35     } 
 36     switch(n)
 37     {
 38         case 1: //添加到左结点 
 39             if(bt->left) //左子树不为空 
 40             {
 41                 printf("左子树结点不为空!\n");
 42                 return 0;
 43             }else
 44                 bt->left=node;
 45             break;
 46         case 2://添加到右结点
 47             if( bt->right) //右子树不为空 
 48             {
 49                 printf("右子树结点不为空!\n"); 
 50                 return 0;
 51             }else
 52                 bt->right=node;
 53             break;
 54         default:
 55             printf("参数错误!\n");
 56             return 0;
 57     }
 58     return 1;
 59 }
 60 ThreadBinTree *BinTreeLeft(ThreadBinTree *bt) //返回左子结点 
 61 {
 62     if(bt)
 63         return bt->left;
 64     else
 65         return NULL;
 66 }
 67 ThreadBinTree *BinTreeRight(ThreadBinTree *bt) //返回右子结点 
 68 {
 69     if(bt)
 70         return bt->right;
 71     else
 72         return NULL;
 73 }
 74 int BinTreeIsEmpty(ThreadBinTree *bt) //检查二叉树是否为空,为空则返回1,否则返回0 
 75 {
 76     if(bt)
 77         return 0;
 78     else
 79         return 1;
 80 } 
 81 int BinTreeDepth(ThreadBinTree *bt) //求二叉树深度
 82 {
 83     int dep1,dep2;
 84     if(bt==NULL)
 85         return 0; //对于空树,深度为0
 86     else
 87     {
 88         dep1 = BinTreeDepth(bt->left); //左子树深度 (递归调用)
 89         dep2 = BinTreeDepth(bt->right); //右子树深度 (递归调用)
 90         if(dep1>dep2)
 91            return dep1 + 1; 
 92         else
 93             return dep2 + 1; 
 94     } 
 95 } 
 96 ThreadBinTree *BinTreeFind(ThreadBinTree *bt,DATA data) //在二叉树中查找值为data的结点 
 97 {
 98     ThreadBinTree *p;
 99     if(bt==NULL)
100         return NULL;
101     else
102     {
103         if(bt->data==data)
104             return bt; 
105         else{ // 分别向左右子树递归查找 
106             if(p=BinTreeFind(bt->left,data))
107                 return p;
108             else if(p=BinTreeFind(bt->right, data)) 
109                 return p;
110             else
111                 return NULL; 
112         } 
113     } 
114 } 
115 void BinTreeClear(ThreadBinTree *bt) // 清空二叉树,使之变为一棵空树
116 {
117      if(bt)
118      {
119          BinTreeClear(bt->left); //清空左子树 
120          BinTreeClear(bt->right);//清空右子树 
121          free(bt);//释放当前结点所占内存 
122          bt=NULL;
123      }
124      return; 
125 }
126 void BinTree_DLR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p))  //先序遍历 
127 {     
128      if(bt)//树不为空,则执行如下操作 
129      {
130          oper(bt); //处理结点的数据 
131          BinTree_DLR(bt->left,oper);
132          BinTree_DLR(bt->right,oper);
133      }
134      return; 
135 } 
136 void BinTree_LDR(ThreadBinTree *bt,void(*oper)(ThreadBinTree *p))  //中序遍历 
137 {
138      if(bt)//树不为空,则执行如下操作 
139      {
140          BinTree_LDR(bt->left,oper); //中序遍历左子树
141          oper(bt);//处理结点数据 
142          BinTree_LDR(bt->right,oper); //中序遍历右子树/
143      }
144      return; 
145 } 
146 void BinTree_LRD(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //后序遍历
147 {
148      if(bt)
149      {
150          BinTree_LRD(bt->left,oper); //后序遍历左子树 
151          BinTree_LRD(bt->right,oper); //后序遍历右子树/
152          oper(bt); //处理结点数据
153      }
154      return; 
155 } 
156 void BinTree_Level(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //按层遍历 
157 {
158      ThreadBinTree *p;
159      ThreadBinTree *q[QUEUE_MAXSIZE]; //定义一个顺序栈 
160      int head=0,tail=0;//队首、队尾序号 
161      if(bt)//若队首指针不为空     
162      {
163          tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列队尾序号 
164          q[tail] = bt;//将二叉树根指针进队
165      }
166      while(head!=tail) //队列不为空,进行循环 
167      {
168          head=(head+1)%QUEUE_MAXSIZE; //计算循环队列的队首序号 
169          p=q[head]; //获取队首元素 
170          oper(p);//处理队首元素 
171          if(p->left!=NULL) //若结点存在左子树,则左子树指针进队 
172          {
173              tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 
174              q[tail]=p->left;//将左子树指针进队 
175          }
176                  
177          if(p->right!=NULL)//若结点存在右孩子,则右孩子结点指针进队 
178          {
179              tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 
180              q[tail]=p->right;//将右子树指针进队 
181          }
182      }
183      return; 
184 }
185 void BinTreeThreading_LDR(ThreadBinTree *bt)     //将二叉树p中序线索化
186 {
187     if(bt) //p非空时,当前访问结点是*p
188     {
189         BinTreeThreading_LDR(bt->left); //递归调用,将左子树线索化
190         //以下直至右子树线索化之前相当于遍历算法中访问结点的操作
191         bt->lflag=(bt->left)?SubTree:Thread; //设置左指针域的标志
192         bt->rflag=(bt->right)?SubTree:Thread;//设置右指针域的标志
193         if(Previous) //若p的前趋Previous存在
194         {
195             if(Previous->rflag==Thread) //若*p的前驱右标志为线索
196                 Previous->right=bt;//令*Previous的右线索指向后继
197             if(bt->lflag==Thread) //*p的左标志为线索
198                 bt->left=Previous;//令*p的左线索指向中序前驱 
199         }
200         Previous=bt;//让Previous保存刚访问的结点
201         BinTreeThreading_LDR(bt->right);//递归调用,将右子树线索化
202     }
203 }
204 ThreadBinTree *BinTreeNext_LDR(ThreadBinTree *bt) //求指定结点的后继 
205 {
206     ThreadBinTree *nextnode;
207     if(!bt) return NULL; //若当前结点为空,则返回空 
208     if(bt->rflag==Thread) //若当前结点的右子树为空
209         return bt->right; //返回右线索所指的中序后继
210     else{
211         nextnode=bt->right; //从当前结点的右子树开始查找
212         while(nextnode->lflag==SubTree) //循环处理所有左子树不为空的结点
213             nextnode=nextnode->left;
214         return nextnode; //返回左下方的结点
215     }
216 }
217 ThreadBinTree *BinTreePrevious_LDR(ThreadBinTree *bt) //求指定结点的前驱 
218 {
219     ThreadBinTree *prenode;
220     if(!bt) return NULL; //若当前结点为空,则返回空 
221     if(bt->lflag==Thread) //若当前结点的左子树为空
222         return bt->left; //返回左线索所指的中序后继
223     else{
224         prenode=bt->left; //从当前结点的左子树开始查找
225         while(prenode->rflag==SubTree) //循环处理所有右子树不为空的结点
226             prenode=prenode->left;
227         return prenode; //返回左下方的结点
228     }
229 }
230 
231 void ThreadBinTree_LDR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //遍历中序线索二叉树
232 {
233     if(bt) //二叉树不为空
234     {
235         while(bt->lflag==SubTree)//有左子树 
236             bt=bt->left; //从根往下找最左下结点,即中序序列的开始结点
237         do{
238            oper(bt); //处理结点 
239            bt=BinTreeNext_LDR(bt);//找中序后继结点
240         }while(bt);
241     }
242 }
243 
244 void main()

3-4 ThreadBinTreeTest.c

 1 #include <stdio.h> 
 2 #include "3-3 ThreadBinTree.c"
 3 void oper(ThreadBinTree *p) //操作二叉树结点数据
 4 {
 5      printf("%c ",p->data); //输出数据
 6      return;
 7 }
 8 ThreadBinTree *InitRoot()  //初始化二叉树的根 
 9 {
10     ThreadBinTree *node;
11     if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存
12     {
13         printf("\n输入根结点数据:");
14         scanf("%s",&node->data);
15         node->left=NULL;
16         node->right=NULL;
17         return BinTreeInit(node);
18     }
19     return NULL;
20 }
21 void AddNode(ThreadBinTree *bt)
22 {
23      ThreadBinTree *node,*parent;
24      DATA data;
25      char select;
26     if(node=(ThreadBinTree *)malloc(sizeof(ThreadBinTree))) //分配内存
27     {
28         printf("\n输入二叉树结点数据:");
29         fflush(stdin);//清空输入缓冲区 
30         scanf("%s",&node->data);
31         node->left=NULL; //设置左右子树为空 
32         node->right=NULL;
33         
34 
35         printf("输入父结点数据:");
36         fflush(stdin);//清空输入缓冲区 
37         scanf("%s",&data);
38         parent=BinTreeFind(bt,data);//查找指定数据的结点 
39         if(!parent)//若未找到指定数据的结点 
40         {
41             printf("未找到父结点!\n");
42             free(node); //释放创建的结点内存 
43             return;
44          }
45          printf("1.添加到左子树\n2.添加到右子树\n");
46          do{
47             select=getch();
48             select-=0;
49             if(select==1 || select==2)
50                 BinTreeAddNode(parent,node,select); //添加结点到二叉树 
51          }while(select!=1 && select!=2);
52     }
53     return ;
54 }
55 int main() 
56 {
57     ThreadBinTree *root=NULL; //root为指向二叉树根结点的指针 
58     char select;
59     void (*oper1)(); //指向函数的指针 
60     oper1=oper; //指向具体操作的函数 
61     do{
62         printf("\n1.设置二叉树根元素    2.添加二叉树结点\n");
63         printf("3.生成中序线索二叉树  4.遍历线索二叉树\n");
64         printf("0.退出\n");
65         select=getch();
66         switch(select){
67         case 1: //设置根元素 
68              root=InitRoot();
69              break;
70         case 2: //添加结点 
71              AddNode(root);
72              break;
73         case 3://生成中序线索二叉树
74              BinTreeThreading_LDR(root);
75              printf("\n生成中序线索二叉树完毕!\n");
76              break;
77         case 4://遍历中序线索二叉树 
78              printf("\n中序线索二叉树遍历的结果:");
79              ThreadBinTree_LDR(root,oper1);
80              printf("\n");
81              break;
82         case 0:
83              break;
84         }
85     }while(select!=0);
86     BinTreeClear(root);//清空二叉树 
87     root=NULL;
88     getch();
89     return 0;
90 }

 

#include <stdio.h> #include <stdlib.h> #define QUEUE_MAXSIZE 50typedefchar DATA; //定义元素类型 typedefenum { SubTree, Thread }NodeFlag; //枚举值SubTree(子树)和Thread(线索)分别为0,1typedefstruct ThreadTree //定义线索二叉树结点类型 { DATA data; //元素数据 NodeFlag lflag; //左标志 NodeFlag rflag; //右标志 struct ThreadTree *left; //左子树结点指针struct ThreadTree *right; //右子树结点指针 }ThreadBinTree; ThreadBinTree *Previous=NULL; //前驱结点指针 ThreadBinTree *BinTreeInit(ThreadBinTree *node) //初始化二叉树根结点 { if(node!=NULL) //若二叉树根结点不为空 return node; elsereturn NULL; } int BinTreeAddNode(ThreadBinTree *bt,ThreadBinTree *node,int n) //添加数据到二叉树 //bt为父结点,node为子结点,n=1表示添加左子树,n=2表示添加右子树 { if(bt==NULL) { printf("父结点不存在,请先设置父结点!\n"); return0; } switch(n) { case1: //添加到左结点 if(bt->left) //左子树不为空 { printf("左子树结点不为空!\n"); return0; }else bt->left=node; break; case2://添加到右结点if( bt->right) //右子树不为空 { printf("右子树结点不为空!\n"); return0; }else bt->right=node; break; default: printf("参数错误!\n"); return0; } return1; } ThreadBinTree *BinTreeLeft(ThreadBinTree *bt) //返回左子结点 { if(bt) return bt->left; elsereturn NULL; } ThreadBinTree *BinTreeRight(ThreadBinTree *bt) //返回右子结点 { if(bt) return bt->right; elsereturn NULL; } int BinTreeIsEmpty(ThreadBinTree *bt) //检查二叉树是否为空,为空则返回1,否则返回0 { if(bt) return0; elsereturn1; } int BinTreeDepth(ThreadBinTree *bt) //求二叉树深度 { int dep1,dep2; if(bt==NULL) return0; //对于空树,深度为0else { dep1 = BinTreeDepth(bt->left); //左子树深度 (递归调用) dep2 = BinTreeDepth(bt->right); //右子树深度 (递归调用)if(dep1>dep2) return dep1 + 1; elsereturn dep2 + 1; } } ThreadBinTree *BinTreeFind(ThreadBinTree *bt,DATA data) //在二叉树中查找值为data的结点 { ThreadBinTree *p; if(bt==NULL) return NULL; else { if(bt->data==data) return bt; else{ // 分别向左右子树递归查找 if(p=BinTreeFind(bt->left,data)) return p; elseif(p=BinTreeFind(bt->right, data)) return p; elsereturn NULL; } } } void BinTreeClear(ThreadBinTree *bt) // 清空二叉树,使之变为一棵空树 { if(bt) { BinTreeClear(bt->left); //清空左子树 BinTreeClear(bt->right);//清空右子树 free(bt);//释放当前结点所占内存 bt=NULL; } return; } void BinTree_DLR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //先序遍历 { if(bt)//树不为空,则执行如下操作 { oper(bt); //处理结点的数据 BinTree_DLR(bt->left,oper); BinTree_DLR(bt->right,oper); } return; } void BinTree_LDR(ThreadBinTree *bt,void(*oper)(ThreadBinTree *p)) //中序遍历 { if(bt)//树不为空,则执行如下操作 { BinTree_LDR(bt->left,oper); //中序遍历左子树 oper(bt);//处理结点数据 BinTree_LDR(bt->right,oper); //中序遍历右子树/ } return; } void BinTree_LRD(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //后序遍历 { if(bt) { BinTree_LRD(bt->left,oper); //后序遍历左子树 BinTree_LRD(bt->right,oper); //后序遍历右子树/ oper(bt); //处理结点数据 } return; } void BinTree_Level(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //按层遍历 { ThreadBinTree *p; ThreadBinTree *q[QUEUE_MAXSIZE]; //定义一个顺序栈 int head=0,tail=0;//队首、队尾序号 if(bt)//若队首指针不为空 { tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列队尾序号 q[tail] = bt;//将二叉树根指针进队 } while(head!=tail) //队列不为空,进行循环 { head=(head+1)%QUEUE_MAXSIZE; //计算循环队列的队首序号 p=q[head]; //获取队首元素 oper(p);//处理队首元素 if(p->left!=NULL) //若结点存在左子树,则左子树指针进队 { tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 q[tail]=p->left;//将左子树指针进队 } if(p->right!=NULL)//若结点存在右孩子,则右孩子结点指针进队 { tail=(tail+1)%QUEUE_MAXSIZE;//计算循环队列的队尾序号 q[tail]=p->right;//将右子树指针进队 } } return; } void BinTreeThreading_LDR(ThreadBinTree *bt) //将二叉树p中序线索化 { if(bt) //p非空时,当前访问结点是*p { BinTreeThreading_LDR(bt->left); //递归调用,将左子树线索化//以下直至右子树线索化之前相当于遍历算法中访问结点的操作 bt->lflag=(bt->left)?SubTree:Thread; //设置左指针域的标志 bt->rflag=(bt->right)?SubTree:Thread;//设置右指针域的标志if(Previous) //若p的前趋Previous存在 { if(Previous->rflag==Thread) //若*p的前驱右标志为线索 Previous->right=bt;//令*Previous的右线索指向后继if(bt->lflag==Thread) //*p的左标志为线索 bt->left=Previous;//令*p的左线索指向中序前驱 } Previous=bt;//让Previous保存刚访问的结点 BinTreeThreading_LDR(bt->right);//递归调用,将右子树线索化 } } ThreadBinTree *BinTreeNext_LDR(ThreadBinTree *bt) //求指定结点的后继 { ThreadBinTree *nextnode; if(!bt) return NULL; //若当前结点为空,则返回空 if(bt->rflag==Thread) //若当前结点的右子树为空return bt->right; //返回右线索所指的中序后继else{ nextnode=bt->right; //从当前结点的右子树开始查找while(nextnode->lflag==SubTree) //循环处理所有左子树不为空的结点 nextnode=nextnode->left; return nextnode; //返回左下方的结点 } } ThreadBinTree *BinTreePrevious_LDR(ThreadBinTree *bt) //求指定结点的前驱 { ThreadBinTree *prenode; if(!bt) return NULL; //若当前结点为空,则返回空 if(bt->lflag==Thread) //若当前结点的左子树为空return bt->left; //返回左线索所指的中序后继else{ prenode=bt->left; //从当前结点的左子树开始查找while(prenode->rflag==SubTree) //循环处理所有右子树不为空的结点 prenode=prenode->left; return prenode; //返回左下方的结点 } } void ThreadBinTree_LDR(ThreadBinTree *bt,void (*oper)(ThreadBinTree *p)) //遍历中序线索二叉树 { if(bt) //二叉树不为空 { while(bt->lflag==SubTree)//有左子树 bt=bt->left; //从根往下找最左下结点,即中序序列的开始结点do{ oper(bt); //处理结点 bt=BinTreeNext_LDR(bt);//找中序后继结点 }while(bt); } } void main()

3.1 层次关系结构:树(2)

标签:

原文地址:http://www.cnblogs.com/wozixiaoyao/p/5683127.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!