二叉樹的操作實現
這里的二叉樹全部都是用二叉鏈實現,算法都是一些簡單的遞歸
- 根據二叉樹括號表示法字符串str生成對應的二叉樹鏈式存儲結構
- 輸出二叉樹
- 先序遍歷、中序遍歷、后序遍歷
- 銷毀二叉樹
- 查找值為x的結點
- 求二叉樹的高度
- 求二叉樹元素的最大值
- 求二叉樹結點個數
- 輸出所有的葉子結點
- 求二叉樹中結點值x的層數
- 求二叉樹第k層的結點個數
- 求第k層上葉子結點的個數
- 求二叉樹中所有單分支結點個數
- 判斷兩棵樹是否相似
- 輸出值為x的結點的所有祖先
- 輸出值為x的結點的所有子孫結點
- 判斷值為x的結點和值為y的結點是否為兄弟
- 將二叉樹b1復制到二叉樹b2
- 將二叉樹的所有左右子樹進行交換
- 判斷一顆二叉樹是否是完全二叉樹
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 typedef char ElemType; 5 typedef struct node 6 { 7 ElemType data; 8 struct node *lchild; 9 struct node *rchild; 10 }BTNode; 11 12 const int MaxSize = 100 + 10; 13 14 //根據二叉樹括號表示法字符串str生成對應的二叉樹鏈式存儲結構 15 void CreateBTree(BTNode * &b, char *str) 16 { 17 BTNode *St[MaxSize], *p; //St作為順序棧 18 int top = -1, k,j = 0; //top作為棧頂指針 19 char ch; 20 b = NULL; 21 ch = str[j]; 22 while (ch != '\0') 23 { 24 switch (ch) 25 { 26 case '(':top++; St[top] = p; k = 1; break; //開始處理左孩子結點 27 case ')':top--; break; //棧頂結點的子樹處理完畢 28 case ',':k = 2; break; //開始處理右孩子結點 29 default: 30 p = (BTNode *)malloc(sizeof(BTNode)); //創建一個結點,由p指向它 31 p->data = ch; 32 p->lchild = p->rchild = NULL; 33 if (b == NULL) b = p; //若尚未創建根節點 34 else 35 { 36 switch (k) 37 { 38 case 1:St[top]->lchild = p; break; 39 case 2:St[top]->rchild = p; break; 40 } 41 } 42 } 43 j++; //繼續掃描str 44 ch = str[j]; 45 } 46 } 47 48 //輸出二叉樹DispBTree(b) 49 void DispBTree(BTNode *b) 50 { 51 if (b != NULL) 52 { 53 printf("%c", b->data); 54 if (b->lchild != NULL || b->rchild != NULL) 55 { 56 printf("("); //有孩子結點時才輸出“(” 57 DispBTree(b->lchild); //遞歸處理左子樹 58 if (b->rchild != NULL) printf(","); //有右孩子結點時才輸出“,” 59 DispBTree(b->rchild); //遞歸處理右子樹 60 printf(")"); //有孩子結點時才輸出 61 } 62 } 63 } 64 65 //先序遍歷 66 void PreOrder(BTNode * b) 67 { 68 if (b != NULL) 69 { 70 printf("%c", b->data); 71 PreOrder(b->lchild); 72 PreOrder(b->rchild); 73 } 74 } 75 //中序遍歷 76 void InOrder(BTNode * b) 77 { 78 if (b != NULL) 79 { 80 InOrder(b->lchild); 81 printf("%c", b->data); 82 InOrder(b->rchild); 83 } 84 } 85 //后序遍歷 86 void PostOrder(BTNode * b) 87 { 88 if (b != NULL) 89 { 90 InOrder(b->lchild); 91 InOrder(b->rchild); 92 printf("%c", b->data); 93 } 94 } 95 96 //銷毀二叉樹 97 void DestroyBTree(BTNode *& b) 98 { 99 if (b != NULL) 100 { 101 DestroyBTree(b->lchild); 102 DestroyBTree(b->rchild); 103 free(b); 104 } 105 } 106 107 108 //查找值為x的結點 109 BTNode *FindNode(BTNode *b, ElemType x) 110 { 111 BTNode *p; 112 if (b == NULL) return NULL; 113 else if (b->data == x) return b; 114 else 115 { 116 p = FindNode(b->lchild, x); 117 if (p != NULL) return p; 118 else return FindNode(b->rchild, x); 119 } 120 } 121 122 //求二叉樹的高度 123 int BTHeight(BTNode *b) 124 { 125 int lchildh, rchildh; 126 if (b == NULL) return 0; 127 else 128 { 129 lchildh = BTHeight(b->lchild); 130 rchildh = BTHeight(b->rchild); 131 return lchildh > rchildh ? (lchildh + 1) : (rchildh + 1); 132 } 133 } 134 135 //求二叉樹元素的最大值 136 int BTMax(BTNode *b) 137 { 138 if (b == NULL) return 0; 139 else 140 { 141 int m1 = BTMax(b->lchild); 142 int m2 = BTMax(b->rchild); 143 int m3 = b->data; 144 if (m1 > m2) return m1 > m3 ? m1 : m3; 145 else return m2 > m3 ? m2 : m3; 146 } 147 } 148 149 //求二叉樹結點個數 150 int BTNum(BTNode * b) 151 { 152 if (b == NULL) return 0; 153 else return BTNum(b->lchild) + BTNum(b->rchild) + 1; 154 } 155 156 //輸出所有的葉子結點 157 void DispLeaf(BTNode *b) 158 { 159 if (b != NULL) 160 { 161 if (b->lchild == NULL && b->rchild == NULL) 162 printf("%c", b->data); 163 DispLeaf(b->lchild); 164 DispLeaf(b->rchild); 165 } 166 } 167 168 //求二叉樹中結點值x的層數 169 //返回0表示未找到,h初始置為0 170 int BTLevel(BTNode *b, ElemType x, int h) 171 { 172 int level; 173 if (b == NULL) return 0; 174 else if (b->data == x) return h; 175 else 176 { 177 level = BTLevel(b->lchild, x, h + 1); 178 if (level != 0) return level; 179 else return BTLevel(b->rchild, x, h + 1); 180 } 181 } 182 183 //求二叉樹第k層的結點個數 184 //當前層數h初始置為0 185 int BTKlevel(BTNode *b,int h, int k) 186 { 187 if (b == NULL) return 0; 188 else 189 { 190 if (h == k) return 1; 191 if (h < k) return (BTKlevel(b->lchild, h + 1, k) + BTKlevel(b->rchild,h + 1,k)); 192 } 193 } 194 195 //求第k層上葉子結點的個數 196 int BTKlevelLeaf(BTNode *b, int h, int k) 197 { 198 if (b == NULL) return 0; 199 else 200 { 201 if (h == k && b->lchild == NULL && b->rchild == NULL) return 1; 202 if (h < k) return (BTKlevelLeaf(b->lchild, h + 1, k) + BTKlevelLeaf(b->rchild, h + 1, k)); 203 } 204 return 0; //其它情況返回0 205 } 206 207 //求二叉樹中所有單分支結點個數 208 int BTSingleSonNode(BTNode * b) 209 { 210 if (b == NULL) return 0; 211 else if ((b->lchild == NULL && b->rchild != NULL) || (b->lchild != NULL && b->rchild == NULL)) return BTSingleSonNode(b->lchild) + BTSingleSonNode(b->rchild) + 1; 212 else return BTSingleSonNode(b->lchild) + BTSingleSonNode(b->rchild); 213 } 214 215 //判斷兩棵樹是否相似 216 //形態一樣,結點值可以不同 217 bool BTLike(BTNode *b1, BTNode *b2) 218 { 219 bool flag1, flag2; 220 if (b1 == NULL && b2 == NULL) return true; 221 else if (b1 == NULL || b2 == NULL) return false; 222 else 223 { 224 flag1 = BTLike(b1->lchild, b2->lchild); 225 flag2 = BTLike(b1->rchild, b2->rchild); 226 return flag1 && flag2; 227 } 228 } 229 230 //輸出值為x的結點的所有祖先 231 //f(b,x)=true表示以結點b為根節點的二叉樹包含x 232 bool BTAncestor(BTNode *b, ElemType x) 233 { 234 if (b == NULL) return false; 235 else if ((b->lchild != NULL && b->lchild->data == x) || (b->rchild != NULL && b->rchild->data == x)) 236 { 237 printf("%c", b->data); 238 return true; 239 } 240 else 241 { 242 int flag1 = BTAncestor(b->lchild, x); 243 int flag2 = BTAncestor(b->rchild, x); //考慮到可能存在多個x,分開寫 244 if(flag1 || flag2) printf("%c", b->data); 245 return true; 246 } 247 return false; 248 } 249 250 //輸出值為x的結點的所有子孫結點 251 void BTChild(BTNode *b, ElemType x) 252 { 253 if (b != NULL) 254 { 255 if (b->data == x) 256 { 257 PreOrder(b->lchild); 258 PreOrder(b->rchild); 259 } 260 else 261 { 262 BTChild(b->lchild,x); 263 BTChild(b->rchild,x); 264 } 265 } 266 } 267 268 //判斷值為x的結點和值為y的結點是否為兄弟 269 bool BTBrother(BTNode *b, ElemType x, ElemType y) 270 { 271 if (b == NULL) return false; 272 else 273 { 274 if (b->lchild != NULL && b->rchild != NULL) 275 if ((b->lchild->data == x && b->rchild->data == y) || (b->lchild->data == y && b->rchild->data == x)) 276 return true; 277 return BTBrother(b->lchild, x, y) || BTBrother(b->rchild, x, y); 278 } 279 } 280 281 //將二叉樹b1復制到二叉樹b2 282 void BTCopy(BTNode *b1, BTNode * &b2) 283 { 284 if (b1 == NULL) b2 = NULL; 285 else 286 { 287 b2 = (BTNode *)malloc(sizeof(BTNode)); 288 b2->data = b1->data; 289 BTCopy(b1->lchild, b2->lchild); 290 BTCopy(b1->rchild, b2->rchild); 291 } 292 } 293 294 //將二叉樹的所有左右子樹進行交換 295 void BTSwap(BTNode *b1, BTNode * &b2) 296 { 297 if (b1 == NULL) b2 = NULL; 298 else 299 { 300 b2 = (BTNode *)malloc(sizeof(BTNode)); 301 b2->data = b1->data; 302 BTSwap(b1->rchild, b2->lchild); 303 BTSwap(b1->lchild, b2->rchild); 304 } 305 } 306 307 308 //判斷一顆二叉樹是否是完全二叉樹 309 //兩條規則,違反任意一條均不是完全二叉樹 310 //1、某結點無左孩子,則一定沒有右孩子 311 //2、若某結點缺少左孩子或右孩子,則其所有后繼(層次遍歷的后繼)一定無孩子 312 bool BTComp(BTNode *b) 313 { 314 BTNode *Qu[MaxSize], *p; //定義一個隊列用於層次遍歷 315 int front = 0, rear = 0; //環形隊列的隊頭和隊尾指針 316 bool cm = true; //cm為真表示二叉樹為完全二叉樹 317 bool flag = true; //flag為真表示所有結點到目前為止都有左右孩子 318 if (b == NULL) return true; 319 rear++; 320 Qu[rear] = b; //根結點入隊 321 while (front != rear) //隊列不為空 322 { 323 front = (front + 1) % MaxSize; 324 p = Qu[front]; //隊首出隊 325 if (p->lchild == NULL) 326 { 327 flag = false; 328 if (p->rchild != NULL) //沒有左孩子,則一定沒有右孩子 329 { 330 cm = false; 331 break; 332 } 333 } 334 else 335 { 336 if ((!flag)) //出現空缺少左孩子或右孩子之后,所有的結點均無孩子 337 { 338 cm = false; 339 break; 340 } 341 rear = (rear + 1) % MaxSize; 342 Qu[rear] = p->lchild; //左孩子入隊 343 if (p->rchild == NULL) flag = false; 344 else 345 { 346 rear = (rear + 1) % MaxSize; 347 Qu[rear] = p->rchild; //右孩子入隊 348 } 349 } 350 } 351 return cm; 352 } 353 354 int main() 355 { 356 BTNode *b1, *b2; 357 char str1[] = "A(B(D(,G)),C(E(,G),F))"; 358 char str2[] = "A(B(D,D),C(E))"; 359 CreateBTree(b2,str2); 360 printf("%d\n", BTComp(b2)); 361 return 0; 362 }
參考資料:《數據結構教程》李春葆等