二叉樹的基本操作


實驗內容

設計一個與二叉樹基本操作相關的演示程序,要求實現以下功能:

(1)創建二叉樹。按照用戶需要的二叉樹,構建二叉樹。

(2)將創建的二叉樹以樹狀形式輸出。

(3)分別以先序,中序,后序三種遍歷方式訪問二叉樹。

(4)輸出二叉樹的葉子結點以及葉子結點的個數。

(5)輸出二叉樹的高度。

存儲結構設計

本程序采用二叉鏈式存儲結構(BiTNode)存儲二叉樹的結點信息。二叉樹的鏈表中的結點至少包括三個域:數據域(data),左孩子指針域(LChild),右孩子指針域(RChild)。

系統功能設計

本程序除了完成二叉樹的創建功能外,還設置了8個子功能菜單。由於這8個子功能都是建立在二叉樹的構造上,所以二叉樹的創建由主函數main()完成。8個子功能設計描述如下:

(1)樹狀輸出二叉樹。樹狀輸出二叉樹由函數TranslevelPrint()實現。當用戶選擇該功能時,系統以樹狀的形式輸出用戶所創建的二叉樹。

(2)先序遍歷二叉樹。由函數PreOrder()實現。該功能按照先序遍歷訪問二叉樹的方法輸出先序序列。

(3)中序遍歷二叉樹。由函數InOrder()實現。該功能按照中序遍歷訪問二叉樹的方法輸出中序序列。

(4)后序遍歷二叉樹。由函數PostOrder()實現。該功能按照后序遍歷訪問二叉樹的方法輸出后序序列。

(5)輸出葉子結點。該功能采用先序遍歷二叉樹的方法,依次輸出葉子結點。由函數PreOrderLeaf()實現。

(6)輸出葉子結點個數。該功能計算並輸出二叉樹葉子結點的個數,由LeafCount()函數實現。采用遞歸算法計算二叉樹葉子結點的個數,算法思想是:當二叉樹為空時,葉子總結點數為0;當二叉樹只有一個結點時,葉子結點個數為1;否則,葉子結點總數為左右子樹結點之和。

(7)輸出二叉樹的深度。該功能即輸出二叉樹結點所在層次的最大值。由函數PostOrderDepth()實現。

(8)退出。由函數exit()實現。

  1 #include<conio.h>
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<math.h>
  5 #define MAXLEN 100
  6 #define NLAYER 4
  7 typedef struct BiTNode
  8 {
  9     /* data */
 10     char data;
 11     struct BiTNode *LChild,*RChild;
 12 }BiTNode,*BiTree;
 13 BiTree T;
 14 //建立二叉樹
 15 void CreatBiTree(BiTree *bt)//按照先序序列建造二叉樹
 16 {
 17     char ch;
 18     scanf("%c",&ch);
 19     if(ch=='#') *bt=NULL;
 20     else
 21     {
 22         *bt=(BiTree)malloc(sizeof(BiTNode));//生成一個新的結點
 23         (*bt)->data=ch;
 24         CreatBiTree(&((*bt)->LChild));//生成左子樹
 25         CreatBiTree(&((*bt)->RChild));
 26     }
 27 }
 28 //樹形打印二叉樹
 29 void TranslevelPrint(BiTree bt)
 30 {
 31     //本算法實現二叉樹的按層打印
 32     struct node
 33     {
 34         /* data */
 35         BiTree vec[MAXLEN];//存放樹結點
 36         int layer[MAXLEN];//結點所在的層
 37         int locate[MAXLEN];//打印結點的位置
 38         int front,rear;
 39     }q;  //定義隊列q
 40     int i,j=1,k=0,nlocate;
 41     q.front=0;    q.rear=0;//初始化隊列q隊頭,隊尾
 42     printf("  ");
 43     q.vec[q.rear]=bt;//將二叉樹根節點入隊列
 44     q.layer[q.rear]=1;
 45     q.locate[q.rear]=20;
 46     q.rear=q.rear+1;
 47     while(q.front<q.rear)
 48     {
 49         bt=q.vec[q.front];
 50         i=q.layer[q.front];
 51         nlocate=q.locate[q.front];
 52         if (j<i)   //進層打印時換行
 53         {
 54             printf("\n\n");
 55             j=j+1; k=0;
 56             while(k<nlocate)
 57             {
 58                 printf("  ");
 59                 k++;
 60             }
 61         }
 62         while(k<(nlocate-1))
 63         {
 64             printf("  ");
 65             k++;
 66         }
 67         printf("%c",bt->data );
 68         q.front=q.front+1;
 69         if(bt->LChild !=NULL)//存在左子樹,將左子樹根節點入隊列
 70         {
 71             q.vec[q.rear]=bt->LChild;
 72             q.layer[q.rear]=i+1;
 73             q.locate[q.rear]=(int)(nlocate-pow(2,NLAYER-i-1));
 74             q.rear=q.rear+1;
 75         }
 76         if(bt->RChild !=NULL)
 77         {
 78             q.vec[q.rear]=bt->RChild;
 79             q.layer[q.rear]=i+1;
 80             q.locate[q.rear]=(int)(nlocate+pow(2,NLAYER-i-1));
 81             q.rear=q.rear+1;
 82         }
 83     }
 84 }
 85 //輸出結點
 86 void Visit(char ch)
 87 {
 88     printf("%c",ch );
 89 }
 90 //先序遍歷二叉樹
 91 void PreOrder(BiTree root)
 92 {
 93     //先序遍歷二叉樹,root為指向二叉樹跟結點的指針
 94     if(root!=NULL)
 95     {
 96         Visit(root->data);//訪問根結點
 97         PreOrder(root->LChild);//先序遍歷左子樹
 98         PreOrder(root->RChild);//先序遍歷右子樹
 99     }
100 }
101 //中序遍歷二叉樹
102 void InOrder(BiTree root)
103 {
104     if(root!=NULL)
105     {
106         InOrder(root->LChild);
107         Visit(root->data);
108         InOrder(root->RChild);
109     }
110 }
111 //后序遍歷二叉樹
112 void PostOrder(BiTree root)
113 {
114     if(root!=NULL)
115     {
116         PostOrder(root->LChild);
117         PostOrder(root->RChild);
118         Visit(root->data);
119     }
120 }
121 //輸出葉子結點
122 void PreOrderLeaf(BiTree root)
123 {
124     //先序遍歷二叉樹並輸出葉子結點
125     if(root!=NULL)
126     {
127         if(root->LChild==NULL&& root->RChild==NULL)
128             printf("%c",root->data );//輸出葉子結點
129         PreOrderLeaf(root->LChild);
130         PreOrderLeaf(root->RChild);
131     }
132 }
133 //輸出葉子結點的個數
134 int LeafCount(BiTree root)
135 {
136     int LeafNum;
137     if(root==NULL) LeafNum=0;
138     else if((root->LChild==NULL)&&(root->RChild==NULL))  LeafNum=1;
139     else LeafNum=LeafCount(root->LChild)+LeafCount(root->RChild);
140     //葉子數為左右子樹數目之和
141     return LeafNum;
142 }
143 //輸出二叉樹的深度
144 int PostTreeDepth(BiTree root)
145 {
146     //后序遍歷求二叉樹的深度遞歸算法
147     int hl,hr,max;
148     if(root!=NULL)
149     {
150         hl=PostTreeDepth(root->LChild);//求左子樹的深度
151         hr=PostTreeDepth(root->RChild);//求右子樹的深度
152         max=hl>hr?hl:hr;//得到左右子樹深度較大者
153         return(max+1);
154     }
155     else
156         return 0;
157 }
158 //主要工作函數,操作區用戶界面
159 void mainwork()
160 {
161     int yourchoice;
162     printf("\n-------------------------歡迎使用二叉樹基本操作程序-------------------\n");
163     printf("\n                                菜 單 選 擇                         \n\n");
164     printf("      1.樹狀輸出二叉樹                        2.先序遍歷二叉樹          \n");
165     printf("      3.中序遍歷二叉樹                        4.后序遍歷二叉樹          \n");
166     printf("      5.輸出葉子結點                          6.輸出葉子結點的個數      \n");
167     printf("      7.輸出二叉樹的深度                      8.退出                    \n");
168     printf("\n----------------------------------------------------------------------\n");
169     printf("請輸入您的選擇:");
170     scanf("%d",&yourchoice);
171     while(!(yourchoice==1||yourchoice==2||yourchoice==3||yourchoice==4
172                ||yourchoice==5||yourchoice==6||yourchoice==7||yourchoice==8))
173     {
174         printf("輸入選擇不明確,請重新輸入:\n");
175         scanf("%d",&yourchoice);
176     }
177     while(1)
178     {
179         switch(yourchoice)
180         {
181             case 1:printf("樹的形狀為:\n"); TranslevelPrint(T);getch();break;
182             case 2:printf("先序遍歷序列:\n"); PreOrder(T);getch(); break;
183             case 3:printf("中序遍歷序列:\n"); InOrder(T); getch();break;
184             case 4:printf("后序遍歷序列:\n"); PostOrder(T); getch();break;
185             case 5:printf("葉子結點為:\n");   PreOrderLeaf(T); getch();break;
186             case 6:printf("葉子結點的個數為:%d",LeafCount(T)); getch();break;
187             case 7:printf("二叉樹的深度為:%d",PostTreeDepth(T)); getch();break;
188             case 8:system("cls");exit(0);break;
189         }
190         printf("\n-------------------------歡迎使用二叉樹基本操作程序-------------------\n");
191         printf("\n                                菜 單 選 擇                         \n\n");
192         printf("      1.樹狀輸出二叉樹                        2.先序遍歷二叉樹          \n");
193         printf("      3.中序遍歷二叉樹                        4.后序遍歷二叉樹          \n");
194         printf("      5.輸出葉子結點                          6.輸出葉子結點的個數      \n");
195         printf("      7.輸出二叉樹的深度                      8.退出                    \n");
196         printf("\n----------------------------------------------------------------------\n");
197         printf("請輸入您的選擇:");
198         scanf("%d",&yourchoice);
199     }
200 }
201 //主函數
202 int main()
203 {
204 
205     printf("首先請輸入二叉樹的結點序列:\n");
206     CreatBiTree(&T);
207     printf("請按菜單提示操作:\n");
208     mainwork();
209     return 0;
210 }

測試結果

(1)首先輸入二叉樹結點:

 

(2)出現主界面:

 

(3)分別選擇不同的功能即可得到不同的結果:

 

樹狀輸出: 先序,中序,后序遍歷分別顯示如下:

 

 

 

(4)選擇功能5,6,7即可出現葉子結點,葉子結點的個數,和該二叉樹的深度

 

 

 

最后,選擇功能8,退出該系統。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM