實驗內容
設計一個與二叉樹基本操作相關的演示程序,要求實現以下功能:
(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,退出該系統。