資料結構實驗(二)
阿新 • • 發佈:2020-11-27
二叉樹的建立與遍歷
一、實驗目的
(1)熟練掌握二叉樹的結構特徵,以及各種儲存結構的特點及適用範圍。
(2)掌握在二叉連結串列儲存結構中的常用遍歷方法:先序遞迴遍歷、中序遞迴遍歷、後序遞迴遍歷、中序遍歷非遞迴演算法;瞭解二叉樹的層序遍歷。
(3)瞭解二叉樹遍歷演算法的簡單應用。
二、實驗內容
1.問題描述
已知二叉樹,如圖所示,基於圖示二叉樹程式設計實現以下演算法:
(1) 建立二叉樹,以先序次序輸入二叉樹序列建立二叉樹;
(2) 採用先序遍歷的遞迴演算法遍歷二叉樹,並輸出先序序列;
(3) 採用中序遍歷的遞迴和非遞迴演算法遍歷二叉樹,並輸出中序序列;
(4) 採用後序遍歷的遞迴演算法遍歷二叉樹,並輸出後序序列;
(5) 計算二叉樹的高度並輸出;
(6) 計算二叉樹中所有結點個數並輸出;
(7) 計算二叉樹中葉子結點個數並輸出。
2.實驗要求
(1)設計二叉樹的鏈式儲存結構;
(2)用先序建立的方式建立二叉樹;
(3)每完成一個演算法,及時輸出結果,便於觀察操作結果;
(4)設計測試用例,測試程式的正確性。
3.測試用例
序號 | 輸入 | 輸出 | 說明 |
---|---|---|---|
1. | ABC@@DE@G@@F@@@ | 先序遍歷:ABCDEGF 中序遍歷(遞迴):CBEGDFA 中序遍歷(非遞迴):CBEGDFA 後序遍歷:CGEFDBA 該二叉樹的高度為: 5 該二叉樹中所有結點個數為: 7 該二叉樹中葉子結點個數為: 3 | |
2. |
ABD@@EG@@@C@F@@ | 先序遍歷:ABDEGCF 中序遍歷(遞迴):DBGEACF 中序遍歷(非遞迴):DBGEACF 後序遍歷:DGEBFCA 該二叉樹的高度為: 4 該二叉樹中所有結點個數為: 7 該二叉樹中葉子結點個數為: 3 | |
3. | @ | 空樹 |
三、資料結構及相關函式說明
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 typedef struct TNode * BinTree; /* 二叉樹型別 */ 5 typedef char ElementType; 6 7 8 struct TNode{ /* 樹結點定義 */ 9 ElementType Data; /* 結點資料 */ 10 BinTree Left; /* 指向左子樹 */ 11 BinTree Right; /* 指向右子樹 */ 12 }; 13 typedef int Position; 14 typedef struct SNode * PtrToSNode; 15 struct SNode{ 16 BinTree* Data; 17 int Top; 18 int m; 19 }; 20 typedef PtrToSNode Stack; 21 22 typedef struct QNode* PtrToQNode; 23 struct QNode{ 24 BinTree* Date; 25 Position Front,Rear; 26 int Max_s; 27 }; 28 typedef PtrToQNode Queue; 29 30 31 Stack CreateStack(int MaxSize){ 32 Stack S = (Stack)malloc(MaxSize * sizeof(struct SNode)); 33 S->Data = (BinTree*)malloc(MaxSize * sizeof(struct TNode)); 34 S->Top = -1; 35 S->m = MaxSize; 36 return S; 37 } 38 39 Queue CreateQueue(int Max_s){ 40 Queue Q = (Queue)malloc(sizeof(struct QNode)); 41 Q->Date = (BinTree*)malloc(Max_s*sizeof(struct QNode)); 42 Q->Front = Q->Rear = 0; 43 Q->Max_s = Max_s; 44 return Q; 45 } 46 47 bool IsFull(Stack S){ 48 return (S->Top == S->m - 1); 49 } 50 51 bool IsFull2(Queue Q){ 52 return (Q->Rear+1)%(Q->Max_s) == Q->Front; 53 } 54 55 bool IsEmpty(Stack S){ 56 return(S->Top == -1); 57 } 58 59 bool IsEmpty2(Queue Q){ 60 return Q->Front == Q->Rear; 61 } 62 63 bool AddQ(Queue Q ,BinTree X){//無頭結點鏈式儲存 64 if(IsFull2(Q)){ 65 printf("佇列滿"); 66 return false; 67 } 68 else{ 69 Q->Rear = (Q->Rear+1)%(Q->Max_s); 70 Q->Date[Q->Rear] = X; 71 return true; 72 } 73 } 74 75 BinTree DeleteQ(Queue Q){ 76 if (IsEmpty2(Q)){ 77 printf("佇列空"); 78 return NULL; 79 } 80 else{ 81 Q->Front = (Q->Front+1)%Q->Max_s; 82 return Q->Date[Q->Front]; 83 } 84 } 85 86 bool Push (Stack S,BinTree X){ 87 if(IsFull(S)){ 88 printf("堆疊滿"); 89 return false; 90 91 } 92 else { 93 S->Data[++(S->Top)] = X; 94 return true; 95 } 96 } 97 98 BinTree Pop(Stack S){ 99 if(IsEmpty(S)){ 100 printf("堆疊空"); 101 return NULL; 102 } 103 else{ 104 return (S->Data[(S->Top--)]); 105 } 106 } 107 108 //按先序次序輸入二叉樹中結點的值(一個字元),@表示空樹,構造二叉連結串列表示二叉樹T 109 BinTree CreateBinTree() 110 { 111 ElementType ch; 112 BinTree T; 113 scanf("%c",&ch); 114 if(ch == '@') 115 T = NULL; 116 else { 117 T = (BinTree)malloc(sizeof(struct TNode)); 118 T->Data = ch; 119 T->Left = CreateBinTree(); 120 T->Right = CreateBinTree(); 121 } 122 return T; 123 } 124 125 //先序遍歷 126 void PreorderTraversal(BinTree BT){ 127 if (BT){ 128 printf("%c",BT->Data); 129 PreorderTraversal(BT->Left); 130 PreorderTraversal(BT->Right); 131 } 132 } 133 134 //中序遍歷 135 void InorderTraversal(BinTree BT){ 136 if(BT){ 137 InorderTraversal(BT->Left); 138 printf("%c",BT->Data); 139 InorderTraversal(BT->Right); 140 } 141 } 142 143 //後序遍歷 144 void PostorderTraversal(BinTree BT){ 145 if(BT){ 146 PostorderTraversal(BT->Left); 147 PostorderTraversal(BT->Right); 148 printf("%c",BT->Data); 149 } 150 } 151 152 //中序遍歷非遞迴 153 void InorderTraversal2(BinTree BT){ 154 BinTree T; 155 Stack S = CreateStack(100); 156 T = BT; 157 while(T||!IsEmpty(S)){ 158 while (T){ 159 Push(S,T); 160 T = T->Left; 161 } 162 } 163 T = Pop(S); 164 printf("%c",T->Data); 165 T = T->Right; 166 } 167 168 //輸出二叉樹的高度 169 int GetHeight(BinTree BT){ 170 int HL,HR,MaxH; 171 if(BT){ 172 HL = GetHeight(BT->Left); 173 HR = GetHeight(BT->Right); 174 MaxH = HL>HR?HL:HR; 175 return MaxH+1; 176 } 177 else return 0; 178 } 179 180 //層序遍歷計算結點個數 181 int NodeCount(BinTree BT){ 182 int Count = 0; 183 Queue Q; 184 BinTree T; 185 if(!BT){ 186 return 0; 187 } 188 Q = CreateQueue(100); 189 AddQ(Q,BT); 190 while(!IsEmpty2(Q)){ 191 T = DeleteQ(Q); 192 Count++; 193 /* printf("%d",T->Data); */ 194 if(T->Left) AddQ(Q,T->Left); 195 if(T->Right) AddQ(Q,T->Right); 196 } 197 return Count; 198 } 199 200 //輸出所有葉節點 201 int leafnum = 0; 202 int PreOrderPrintLeaves(BinTree BT){ 203 204 if(BT){ 205 if(!BT->Left&&!BT->Right){ 206 leafnum ++; 207 } 208 PreOrderPrintLeaves(BT->Left); 209 PreOrderPrintLeaves(BT->Right); 210 } 211 return leafnum; 212 } 213 int main() 214 { 215 BinTree BT; 216 int height,count,leafnum; 217 printf("請按先序次序輸入樹的結點,空樹輸入@: "); 218 BT = CreateBinTree(); 219 220 if(BT == NULL){ 221 printf("\n空樹!\n"); 222 }else{ 223 printf("先序遍歷的結果為: "); 224 PreorderTraversal(BT); 225 printf("\n"); 226 227 printf("中序遍歷的結果為(遞迴): "); 228 InorderTraversal(BT); 229 printf("\n"); 230 231 printf("中序遍歷的結果為(非遞迴): "); 232 InorderTraversal(BT); 233 printf("\n"); 234 235 printf("後序遍歷的結果為: "); 236 PostorderTraversal(BT); 237 printf("\n"); 238 239 height = GetHeight(BT); 240 printf("該二叉樹的高度為: %d",height); 241 printf("\n"); 242 243 count = NodeCount(BT); 244 printf("該二叉樹中所有結點個數為: %d",count); 245 printf("\n"); 246 leafnum = PreOrderPrintLeaves(BT) ; 247 printf("該二叉樹中葉子結點個數為: %d",leafnum); 248 printf("\n"); 249 return 0; 250 } 251 }