课程设计 树的应用与实现

任务概述:

(1)采用孩子双亲表示法,创建一棵一般的树,初始化树后添加孩子及其双亲结点,要求从键盘输入树中结点,并且结点数不少于五个;

(2)将树转成对应的二叉树,将结点的第一个孩子作为其左孩子,其余孩子作为其左孩子的右孩子;

(3)实现转换后二叉树的前序、中序、后序的递归遍历算法的实现;

(4)利用栈实现转换后二叉树的前序、中序、后序的非递归遍历算法的实现。

存储结构:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #define OVERFLOW -2
  4 #define OK 0
  5 #define ERROR 0
  6 #define STACK_INIT_SIZE 100//存储空间初始分配量 
  7 #define STACKINCREMENT 10//存储空间分配增量 
  8 #define MAX_TREE_SIZE 21//树的结点数目最大值 
  9 //>>>>>>>>>>>>>>>>>>>>>>>>>>>自定义数据类型<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 10 typedef int Status;//函数返回值状态码类型 
 11 typedef char  ElemType;//树中结点元素类型 
 12 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>结构体定义<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
 13 //孩子结构 
 14 typedef struct CTNode
 15 {
 16     int child;//孩子结点的下标
 17     struct CTNode *next;//指向下一个结点的指针
 18 }*ChildPtr;
 19 //表头结构
 20 typedef struct 
 21 {
 22     ElemType data;//存放在树中的结点的数据
 23     int parent;//存放双亲的下标
 24     ChildPtr firstchild;//指向第一个孩子的指针
 25 }CTBox;
 26 //树结构
 27 typedef struct 
 28 {
 29     CTBox tree[MAX_TREE_SIZE];//结点数组
 30     int n;//结点数目 
 31 }CTree;
 32 //二叉树结点,左孩子,右孩子 
 33 typedef struct BTNode
 34 {
 35     ElemType data;
 36     struct BTNode *lchild,*rchild;
 37 }BTNode,*BTree;
 38 typedef BTree SElemType;
 39 //栈的结构体 
 40 typedef struct{
 41  SElemType *base;//在栈构造和销毁之后,base的值为NULL 
 42  SElemType *top;//栈顶指针 
 43  int stacksize;//当前已分配的存储空间 
 44 }Stack;
 45 //--------------------------------1.采用孩子双亲表示法创建一棵一般的树------------------------------- 
 46 void InitCtree(CTree &T)
 47 {//初始化树 
 48     int i;
 49     printf("请输入树的结点个数:");
 50     scanf("\n%d",&T.n);
 51     printf("依次输入各个结点:\n"); 
 52     for(i=0; i<T.n; i++)
 53     {
 54       fflush(stdin);//清理标准输入流,把多余的未被保存的数据丢掉 
 55       T.tree[i].data = getchar();
 56       T.tree[i].parent = 0;
 57       T.tree[i].firstchild = NULL; 
 58     }
 59 }
 60 void AddChild(CTree &T)
 61 {//添加孩子
 62     int i,j,k;
 63     printf("-----------------------添加孩子及其双亲结点------------------------------------------\n");           
 64     for(k=0; k<T.n; k++)
 65     {
 66       fflush(stdin); //清理标准输入流,把多余的未被保存的数据丢掉
 67       printf("请输入孩子结点及其双亲结点的序号:(用空格隔开)\n");
 68       scanf("%d %d",&i,&j); 
 69       fflush(stdin);
 70       CTNode *p = (CTNode *)malloc(sizeof(CTNode));
 71       p->child = i;
 72       p->next = NULL;
 73      T.tree[i].parent = j;//找到双亲 
 74       if(!T.tree[j].firstchild)
 75           T.tree[j].firstchild = p;
 76       else
 77        {
 78          CTNode *temp = T.tree[j].firstchild;
 79          while(temp->next )
 80           temp = temp->next ;
 81         temp->next  = p;
 82        }
 83     }
 84 }
 85 //---------------------------------------2.将树转换成对应的二叉树------------------------------------------
 86 Status ExchangeTree(BTree &BT,CTree &T)
 87 {
 88     BTNode *p,*q,*t,*pre;//pre指向p的双亲结点 
 89     CTNode *temp;
 90     int m=T.n ;
 91     if(!(p=(BTNode*)malloc(sizeof(BTNode))))
 92      exit (OVERFLOW);
 93     int i=0;
 94     p->data =T.tree [i].data;
 95     p->lchild =NULL;
 96     p->rchild =NULL;
 97     BT=p;
 98     for(i=0;i<m;i++)
 99     {
100         if(p->data !=T.tree [i].data)
101         {
102             if(!p->lchild &&!p->rchild )
103             p=pre;//p没有孩子时,p指向双亲结点 
104             if(p->lchild )
105                {
106              if(T.tree [i].data==p->lchild->data  )
107              pre=p;
108              p=p->lchild ;
109              }
110              if(p->rchild )
111             if(T.tree [i].data==p->rchild ->data)
112              pre=p;
113              p=p->rchild ;
114         }//寻找要转化的根结点 ,让p指向此时要转换的根节点 
115         if(T.tree [i].firstchild)
116             {
117                 int k=T.tree [i].firstchild->child;
118                 q=(BTNode*)malloc(sizeof(BTNode));//为第一个孩子即左孩子分配空间 
119                 q->data =T.tree [k].data;
120                 q->lchild =NULL;
121                 q->rchild =NULL;
122                 p->lchild =q;//p指向其左孩子 
123                 temp=T.tree [i].firstchild;
124                 while(temp->next )//判断是否有兄弟结点 
125             {
126                 t=(BTNode*)malloc(sizeof(BTNode));
127                 int s=temp->next ->child;
128                 t->data =T.tree [s].data;
129                 t->lchild =NULL;
130                 t->rchild =NULL;
131                 q->rchild =t;//右孩子为其兄弟结点 
132                 q=q->rchild ; 
133                 temp=temp->next ; //后移判断是否还有兄弟结点 
134             }
135         }
136     }
137 }
138 //-------------------------------------3.遍历二叉树的递归算法-----------------------------------------------
139 /*先序遍历的递归算法*/
140  void PreOrderTraverse(BTree BT)
141  {
142   if(BT){
143    printf("%c ",BT->data );
144    PreOrderTraverse(BT->lchild );
145    PreOrderTraverse(BT->rchild );
146   }
147   }
148 /*中序遍历的递归算法*/
149 void InOrderTraverse(BTree BT)
150 {
151  if(BT){
152   InOrderTraverse(BT->lchild );
153   printf("%c ",BT->data );
154   InOrderTraverse(BT->rchild );
155  }
156  } 
157 /*后序遍历的递归算法*/
158 void PostOrderTraverse(BTree BT)
159 {
160  if(BT){
161   PostOrderTraverse(BT->lchild );
162   PostOrderTraverse(BT->rchild );
163   printf("%c ",BT->data );
164  }
165  }
166 //----------------------------------------4.遍历的非递归算法--------------------------------------------------
167 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>栈的相关算法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
168  Status InitStack(Stack &S){
169   //构造一个空栈
170   S.base =(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
171   if(!S.base ) exit(OVERFLOW);
172   S.top =S.base ;
173   S.stacksize = STACK_INIT_SIZE;
174   return OK;
175  }  
176  Status Push(Stack &S,SElemType e)
177  {
178   //入栈
179   if(S.top -S.base >=S.stacksize ){
180    //栈满
181    S.base =(SElemType*)realloc(S.base ,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
182    if(!S.base ) exit (OVERFLOW);
183    S.top =S.base +S.stacksize ;
184    S.stacksize += STACKINCREMENT;
185   } 
186   *S.top++=e;
187   return OK;
188  } 
189  Status Pop(Stack &S,SElemType &e){
190   //出栈
191   if(S.top ==S.base ) return ERROR; 
192   e=*--S.top ;
193   return OK;
194  }
195  Status GetTop(Stack S,SElemType &e)
196  {//若栈不空,则用e返回S的栈顶元素,并返回OK,否则返回ERROR
197     if(S.top ==S.base ) return ERROR; 
198     e=*(S.top -1);
199     return OK;
200  }
201  Status StackEmpty(Stack S){
202   return (S.base ==S.top )?true:false;
203  }
204 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>栈的相关算法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 
205 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>遍历的非递归算法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
206 /*先序遍历的非递归算法*/ 
207  void PreOrder(BTree BT)
208  {
209      Stack S;
210     BTree p=BT;
211     InitStack(S);
212     while(p||!StackEmpty(S))
213     {
214       if(p)
215      {
216         Push(S,p);
217         printf("%c ",p->data );
218         p=p->lchild ;
219      }
220      else
221      {
222           Pop(S,p );
223           p=p->rchild ;
224      }
225    }  
226  }
227 /*中序遍历的非递归算法*/ 
228 void InOrder(BTree BT)
229  {
230      Stack S;
231     BTree p=BT;
232     InitStack(S);
233     while(p||!StackEmpty(S))
234     {
235       if(p)
236      {
237         Push(S,p );
238         p=p->lchild ;
239      }
240      else
241      {
242           Pop(S,p );
243          printf("%c ",p->data );
244           p=p->rchild ;
245      }
246    }  
247  }
248 /*后序遍历的非递归算法*/ 
249 /*步骤:
250 对于树中任意一个访问的节点p可以分情况讨论
251 1. p如果是叶子节点,直接输出
252 2. p如果有孩子,且孩子没有被访问过,则按照右孩子,左孩子的顺序依次入栈
253 3. p如果有孩子,而且孩子都已经访问过,则访问p节点*/
254 void PostOrder(BTree BT)
255  {
256      Stack S;
257      SElemType e;
258     BTree p=BT;
259     BTree mark;
260     mark=p;
261     InitStack(S);
262     Push(S,p);
263     while(!StackEmpty(S))
264     {
265         GetTop(S,p);//p等于栈顶指针 
266         if( (p->lchild  == NULL && p->rchild  == NULL) || (p->rchild  == NULL && mark == p->lchild ) || (mark == p->rchild ) )
267         //入栈时按照右孩子,左孩子顺序入栈,则右孩子被标记,左孩子没有或被标记 
268         {
269             printf("%c ",p->data );
270             mark=p;
271             Pop(S,p);
272          } 
273          else
274          {
275              if(p->rchild )
276              Push(S,p->rchild );
277              if(p->lchild )
278              Push(S,p->lchild );
279          }
280     } 
281  }
282 //>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>遍历的非递归算法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
283 //----------------------------------------------主函数--------------------------------------------------------------
284 main()
285 {
286     BTree BT;
287     CTree T;
288     SElemType e;
289     printf("--------------------------孩子双亲表示法表示一棵一般的树---------------------------\n");
290     InitCtree(T);
291     AddChild(T);
292     printf("---------------------------------树的创建已完成-------------------------------------\n");
293     ExchangeTree(BT,T);
294     printf("-------------------------------二叉树的转换已完成-----------------------------------\n");
295     printf("------------------------------二叉树的递归遍历算法----------------------------------\n");
296     printf("前序遍历:"); 
297     PreOrderTraverse(BT);
298     printf("\n");
299     printf("中序遍历:");
300     InOrderTraverse(BT);
301     printf("\n");
302     printf("后序遍历:");
303     PostOrderTraverse(BT);
304     printf("\n");
305     printf("------------------------------二叉树的非递归遍历算法---------------------------------\n");
306     printf("前序遍历:"); 
307     PreOrder(BT);
308     printf("\n");
309     printf("中序遍历:");
310     InOrder(BT);
311     printf("\n");
312     printf("后序遍历:");
313     PostOrder(BT);
314     printf("\n");
315     return 0;
316  }

运行结果:

posted @ 2019-07-22 15:58  糖哲瑞  阅读(625)  评论(0编辑  收藏  举报