二叉樹在數據結構面試中的地位舉足輕重,算得上是大公司面試必問,筆試必考;因為對二叉樹的操作直接反應一個人的數據結構功底有多深厚,基礎知識是否扎實。。。(一點廢話),下面就二叉樹的基本操作說一說二叉樹的知識點,不對之處還請指正。
面試常考的幾個操作:
1:二叉樹的基本性質
2:遞歸建立二叉樹
6:求二叉樹的深度
7:分層遍歷二叉樹
9:求二叉樹的鏡像
10:測試源碼
下面就常用的算法給大家講解這些二叉樹的基本性質。
說明:
所有代碼使用C語言編寫,頭信息,常量如下:
1 ** 2 * 樹的基本操作tree 3 */ 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #define ERROR -1 9 #define OK 1 10 #define OVERFLOW 2 11 #define STACK_INIT_SIZE 100 12 #define STACKINCREMENT 20 13 14 //最大隊列長度 15 #define MAXQSIZE 100 16 17 typedef int Struct; 18 typedef char TElement; 19 typedef int Status; 20 int i = 0; //記錄樹初始化過程,數據的偏移 21 int j = 0; //記錄樹初始化過程,數據的偏移
二叉樹結構體,以及棧、隊列的結構體(層次遍歷,非遞歸要用到)如下:
1 //二叉樹結構體(二叉鏈表存儲結構) 2 typedef struct BiNode{ 3 TElement data; 4 struct BiNode *lchild,*rchild; 5 }BiTNode, *BiTree; 6 7 //棧表示(用於非遞歸) 8 typedef struct{ 9 BiTree *base; 10 BiTree *top; 11 int stacksize; 12 }SqStack; 13 14 //使用隊列,實現層次遍歷 15 typedef struct QNode{ 16 BiTree data; 17 struct QNode *next; 18 }QNode, *QueuePtr; 19 20 typedef struct{ 21 QueuePtr front; 22 QueuePtr rear; 23 }LinkQueue;
一、二叉樹第 i 層上最多有2i-1個節點
二、深度為 k 的二叉樹,最多有2k - 1個節點
三、對於任意一顆二叉樹T,如果其終端節點數為n1度數為2的節點數為n2 則 n1 = n2 + 1;
四、具有n個節點的完全二叉樹深度為[ log2n] + 1;
遞歸常見二叉樹,先從左子樹開始,arr 是調用傳值過去的節點值,i 用於移動數組內的節點值
//創建二叉樹 Struct CreateBiTree(BiTree &T, char arr[]){ if(arr[i] == ' '){ i++; T = NULL; }else{ T = (BiTree)malloc(sizeof(BiNode)); if(!T){ exit(ERROR);//分配空間失敗; } T->data = arr[i]; i++; CreateBiTree(T->lchild, arr); CreateBiTree(T->rchild, arr); } return OK; }
這是三中常規的遍歷二叉樹的方法,用的非常多,不僅便於理解,而且三個函數只是調用順序不同,所以書上頁數先給出了這三種遍歷。當然在面試中也長問到。
1 //先序遍歷(遞歸方法) 2 int PrintTree(BiTree T){ 3 if(T){ 4 printf("%c ",T->data); 5 PrintTree(T->lchild); 6 PrintTree(T->rchild); 7 8 } 9 return OK; 10 } 11 12 //中序遍歷(遞歸方法) 13 int PrintTreeL(BiTree T){ 14 if(T){ 15 PrintTreeL(T->lchild); 16 printf("%c ",T->data); 17 PrintTreeL(T->rchild); 18 } 19 return OK; 20 } 21 22 //后序遍歷(遞歸方法) 23 int PrintTreeR(BiTree T){ 24 if(T){ 25 PrintTreeR(T->lchild); 26 PrintTreeR(T->rchild); 27 printf("%c ",T->data); 28 } 29 return OK; 30 }
非遞歸遍歷在面試中問的非常多,特別是大公司的面試,幾乎是必問,所以這里就非遞歸的方法每個給出了兩種
一、先序遍歷:
先序遍歷這里給出了兩個方法,兩種方法都是借助於棧來實現,具體的棧的操作在最后源程序中都有,看家可以看看,非遞歸的操作比遞歸麻煩得多,第一種方法是:首先根節點入棧,然后while循環一致判斷棧是否為空,第二個while循環一直講左節點入棧,知道左子樹為空。其中PopN(S); 方法是為了將多余的空元素彈出。第二種方法比較推薦開始根節點不入棧,先判斷根節點是否為空,這樣棧空間中不會有空元素,效率高一點,並且便於理解
1 //先序遍歷(非遞歸方法)(方法1) 2 int PrintTree_Re(BiTree T){ 3 SqStack S; 4 InitStack(S);//建立棧 5 Push(S,T); //樹的根節點先入棧 6 BiTree P; 7 while(StackEmpty(S) == 1){ 8 while(GetTop(S,P) && P){ 9 printf("%c ",P->data); 10 Push(S,P->lchild); 11 } 12 PopN(S); 13 if(StackEmpty(S) == 1){ 14 Pop(S,P); 15 Push(S,P->rchild); 16 } 17 } 18 return OK; 19 } 20 21 //先序遍歷(非遞歸方法)(方法2) 22 int PrintTree_Re_T(BiTree T){ 23 SqStack s; 24 InitStack(s); 25 BiTree p; 26 p = T; 27 while(p || StackEmpty(s) == 1){ 28 while(p){ 29 printf("%c ",p->data); 30 Push(s,p); 31 p = p->lchild; 32 } 33 if(StackEmpty(s) == 1){ 34 Pop(s,p); 35 p = p->rchild; 36 } 37 } 38 return OK; 39 }
二、中序遍歷:
中序遍歷這里也給出2種方法。感覺和先序差不多,只是遍歷順序不同,處理的時候方式一樣,這里不再多說。
1 //中序遍歷(非遞歸)(方法1) 2 int PrintTreeL_Re(BiTree T){ 3 SqStack S; 4 InitStack(S);//建立棧 5 Push(S,T); //樹的根節點先入棧 6 BiTree P; 7 while(StackEmpty(S) == 1){ 8 while(GetTop(S,P) && P){ 9 Push(S,P->lchild); 10 } 11 PopN(S); 12 if(StackEmpty(S) == 1){ 13 Pop(S,P); 14 printf("%c ",P->data); 15 Push(S,P->rchild); 16 } 17 } 18 return OK; 19 } 20 21 //中序遍歷(非遞歸)(方法2) 22 int PrintTreeL_Re_T(BiTree T){ 23 SqStack S; 24 InitStack(S);//建立棧 25 BiTree P; 26 P = T; 27 while(P || StackEmpty(S) == 1){ 28 if(P){ 29 Push(S,P); 30 P = P->lchild; 31 }else{ 32 Pop(S,P); 33 printf("%c ",P->data); 34 P = P->rchild; 35 } 36 } 37 return OK; 38 }
二、后序遍歷:
個人感覺后序遍歷的非遞歸是三種遍歷方式中最難的。寫了很長時間,總感覺找不到一種合適的方法來保證孩子節點完全遍歷。下面來說說這種非遞歸的遍歷。其實會了也比較簡單,對於結點P,要保證根結點在左孩子和右孩子訪問之后才能訪問,先將其入棧。如果P不存在左孩子和右孩子,可以直接訪問;或者P 存在左孩子或者右孩子,訪問過左孩子和右孩子后可以直接訪問該結點。其他情況,則將P的右孩子和左孩子依次入棧。這個就會這一種,應該有其他方法,歡迎指出
1 //后序遍歷(非遞歸方法) 2 int PrintTreeR_Re(BiTree T){ 3 SqStack s; 4 InitStack(s);//建立棧 5 Push(s,T); //樹的根節點先入棧 6 BiTree p,q; 7 while(StackEmpty(s) == 1){ 8 GetTop(s,p); 9 if((p->lchild == NULL && p->rchild == NULL) || ( q && ( q == p->lchild || q == p->rchild))){ 10 printf("%c ",p->data); 11 PopN(s); 12 q = p; 13 }else{ 14 if(p->rchild){ 15 Push(s,p->rchild); 16 } 17 if(p->lchild){ 18 Push(s,p->lchild); 19 } 20 } 21 } 22 return OK; 23 }
其實就是遍歷一遍二叉樹,不再多說,看程序便知
1 //統計二叉樹節點的個數 2 void getTreeNodeNum(BiTree T,int &num){ 3 if(!T){ 4 num = 0; 5 } 6 num++; 7 if(T->lchild){ 8 getTreeNodeNum(T->lchild,num); 9 } 10 if(T->rchild){ 11 getTreeNodeNum(T->rchild,num); 12 } 13 }
思想就是從左子樹開始遍歷,遞歸完整個樹結構,如果二叉樹不為空,二叉樹的深度 = max(左子樹深度, 右子樹深度) + 1,參考代碼如下:
1 //得到樹的深度 2 int getTreeHeight(BiTree T){ 3 int hl,hr,max; 4 if(T!=NULL){ 5 hl=getTreeHeight(T->lchild); 6 hr=getTreeHeight(T->rchild); 7 max=hl>hr?hl:hr; 8 return (max+1); 9 }else{ 10 return 0; 11 } 12 }
一、樹的層次結構分層打印與隊列的的先進先出相似,所以我選擇用隊列來完成,首先根節點入隊列,然后左孩子,又孩子以此入隊列,打印即可
1 /*層次遍歷二叉樹(借助隊列實現)*/ 2 void HierarchicalTree_Q(BiTree T){ 3 LinkQueue Q; 4 InitQueue(Q); //建立隊列 5 EnQueue(Q,T); //樹的根節點先入列 6 BiTree Ta; 7 while(Q.front != Q.rear){ 8 DeQueue(Q,Ta); 9 if(Ta->lchild){ 10 EnQueue(Q,Ta->lchild); 11 } 12 if(Ta->rchild){ 13 EnQueue(Q,Ta->rchild); 14 } 15 printf("%c ",Ta->data); 16 } 17 }
二、說到分層如果打印樹的真實結構應該也可以,所以我想借助堆棧來實現,有興趣的可以看一下,思想:其實和層次遍歷一樣,最難的是怎樣控制換行先,我的想法是創建一個標志位*,當前行入棧完畢就插入標志位*遍歷一個節點就把左孩子和右孩子入棧,以此一層一層的打印,代碼檢驗過,不知道還有沒有錯誤,歡迎指正
1 /*層次遍歷二叉樹(並且分層打印)(借助棧實現)*/ 2 void HierarchicalTree_DA(BiTree T){ 3 LinkQueue Q; 4 InitQueue(Q);//建立隊列 5 EnQueue(Q,T);//樹的根節點先入列 6 BiTree Ta1,Tb1,Tc1; 7 8 //創建標志位 9 char data[3] = {'*',' ',' '}; 10 CreateBiTree(Ta1,data); 11 12 //創建移動的指針 13 QueuePtr point; 14 point = Q.front->next;//移動指針先指向頭結點 15 EnQueue(Q,Ta1);//插入標志位 16 printf("\n"); 17 while(point){ 18 //判斷左右節點 19 if(point->data->lchild || point->data->rchild){ 20 if(point->data->lchild){ 21 EnQueue(Q,point->data->lchild); 22 } 23 if(point->data->rchild){ 24 EnQueue(Q,point->data->rchild); 25 } 26 } 27 point = point->next; //指針下移一位 28 if(point->data->data == '*'){ 29 if(!point->next){//判斷是否到結尾(到結尾直接退出) 30 break; 31 } 32 EnQueue(Q,Ta1);//插入標志節點 33 point = point->next; //如果遇到標志位,則指針下移 34 } 35 } 36 37 printf("\n"); 38 //循環輸出節點 39 while(Q.front != Q.rear){ 40 DeQueue(Q,Tc1); 41 char str = Tc1->data; 42 if(str == '*'){ 43 printf("\n"); 44 }else{ 45 printf("%c ",str); 46 } 47 } 48 }
利用遞歸的次數來(孩子節點不為空的條件)來簡介得到k層節點的個數,比較簡單,代碼如下
1 //得到第k層的節點個數 2 int getNodeNum(BiTree T, int k){ 3 if (!T || k < 1){ 4 return 0; 5 } 6 if (k == 1){ 7 return 1; 8 } 9 return getNodeNum(T->lchild, k-1) + getNodeNum(T->rchild, k-1); 10 }
所謂的鏡像其實就是左子樹和右子樹互換顛倒,如下面代碼。
1 //寫出二叉樹的鏡像 2 void getNoClone(BiTree &T){ 3 BiTree Ta; 4 if(T){ 5 Ta = T->lchild; 6 T->lchild = T->rchild; 7 T->rchild = Ta; 8 getNoClone(T->lchild); 9 getNoClone(T->rchild); 10 } 11 }
最后附上完整的測試代碼,其中包含了,隊列的初始化,插入隊列,出隊列操作,棧的初始化,進棧,出棧,得到棧頂元,樹的初始化素等也可以復習一下。中間可定有不對不足的地方,還望大神們多多指正
1 /** 2 * 樹的基本操作tree 3 */ 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #define ERROR -1 9 #define OK 1 10 #define OVERFLOW 2 11 #define STACK_INIT_SIZE 100 12 #define STACKINCREMENT 20 13 14 //最大隊列長度 15 #define MAXQSIZE 100 16 17 typedef int Struct; 18 typedef char TElement; 19 typedef int Status; 20 int i = 0; //記錄樹初始化過程,數據的偏移 21 int j = 0; //記錄樹初始化過程,數據的偏移 22 23 24 //二叉樹結構體(二叉鏈表存儲結構) 25 typedef struct BiNode{ 26 TElement data; 27 struct BiNode *lchild,*rchild; 28 }BiTNode, *BiTree; 29 30 //棧表示 31 typedef struct{ 32 BiTree *base; 33 BiTree *top; 34 int stacksize; 35 }SqStack; 36 37 //使用隊列,實現層次遍歷 38 typedef struct QNode{ 39 BiTree data; 40 struct QNode *next; 41 }QNode, *QueuePtr; 42 43 typedef struct{ 44 QueuePtr front; 45 QueuePtr rear; 46 }LinkQueue; 47 48 49 //初始化隊列 50 Status InitQueue(LinkQueue &Q){ 51 Q.front = Q.rear = (QueuePtr)malloc(sizeof(BiTree));//動態分配空間 52 if(!Q.front){ 53 exit(ERROR);//分配空間失敗 54 } 55 Q.front->next = NULL; 56 return OK; 57 } 58 59 //在隊尾插入新元素 60 Status EnQueue(LinkQueue &Q, BiTree e){ 61 QueuePtr p; 62 p = (QueuePtr)malloc(sizeof(BiTree)); 63 if(!p){ 64 exit(ERROR);//分配失敗 65 } 66 p->data = e; 67 p->next = NULL; 68 Q.rear->next = p; 69 Q.rear = p; 70 return OK; 71 } 72 73 //刪除隊頭元素,並用e返回 74 void DeQueue(LinkQueue &Q,BiTree &e){ 75 76 if(Q.front != Q.rear){//先判斷隊列是否為空 77 QueuePtr p; 78 e = Q.front->next->data; 79 if(Q.front->next == Q.rear){//隊列只有一個元素 80 p = Q.rear; 81 Q.rear = Q.front; 82 Q.front->next = NULL; 83 }else{ 84 p = Q.front->next; 85 Q.front->next = p->next; 86 p->next = NULL; 87 } 88 //free(p->data); 89 } 90 } 91 92 //創建二叉樹 93 Struct CreateBiTree(BiTree &T, char arr[]){ 94 if(arr[i] == ' '){ 95 i++; 96 T = NULL; 97 }else{ 98 T = (BiTree)malloc(sizeof(BiNode)); 99 if(!T){ 100 exit(ERROR);//分配空間失敗; 101 } 102 T->data = arr[i]; 103 i++; 104 CreateBiTree(T->lchild, arr); 105 CreateBiTree(T->rchild, arr); 106 } 107 return OK; 108 } 109 110 //先序遍歷(遞歸方法) 111 int PrintTree(BiTree T){ 112 if(T){ 113 printf("%c ",T->data); 114 PrintTree(T->lchild); 115 PrintTree(T->rchild); 116 117 } 118 return OK; 119 } 120 121 //中序遍歷(遞歸方法) 122 int PrintTreeL(BiTree T){ 123 if(T){ 124 PrintTreeL(T->lchild); 125 printf("%c ",T->data); 126 PrintTreeL(T->rchild); 127 } 128 return OK; 129 } 130 131 //后序遍歷(遞歸方法) 132 int PrintTreeR(BiTree T){ 133 if(T){ 134 PrintTreeR(T->lchild); 135 PrintTreeR(T->rchild); 136 printf("%c ",T->data); 137 } 138 return OK; 139 } 140 141 142 //初始化棧 143 Struct InitStack(SqStack &S){ 144 S.base = (BiTree *)malloc(STACK_INIT_SIZE * sizeof(BiTree)); 145 S.top = S.base; 146 if(!S.base){ 147 exit(ERROR);//分配失敗 148 } 149 S.stacksize = STACK_INIT_SIZE; 150 return OK; 151 } 152 153 //push入棧操作 154 Struct Push(SqStack &S, BiTree T){ 155 if(S.top - S.base >= S.stacksize){ 156 S.base = (BiTree *)realloc(S.base,(S.stacksize + STACKINCREMENT) * sizeof(BiTree)); 157 if(!S.base){ 158 exit(ERROR); 159 } 160 S.top = S.base + S.stacksize; 161 S.stacksize += STACKINCREMENT; 162 } 163 *S.top = T; 164 S.top++; 165 166 return OK; 167 } 168 169 //出棧操作 170 Struct Pop(SqStack &S,BiTree &P){ 171 if(S.base != S.top){ 172 P = *(--S.top); 173 } 174 return OK; 175 } 176 177 //出棧操作 178 Struct PopN(SqStack &S){ 179 if(S.base != S.top){ 180 --S.top; 181 } 182 return OK; 183 } 184 185 //得到棧頂元素操作 186 Struct GetTop(SqStack S,BiTree &P){ 187 if(S.base != S.top){ 188 P = *(S.top - 1); 189 } 190 return OK; 191 } 192 193 //判斷是否是空棧 194 int StackEmpty(SqStack S){ 195 if(S.base != S.top){ 196 return 1; 197 }else{ 198 return 0; 199 } 200 } 201 202 //返回棧長度 203 int GetLength(SqStack S){ 204 return S.top - S.base; 205 } 206 207 //先序遍歷(非遞歸方法)(方法1) 208 int PrintTree_Re(BiTree T){ 209 SqStack S; 210 InitStack(S);//建立棧 211 Push(S,T); //樹的根節點先入棧 212 BiTree P; 213 while(StackEmpty(S) == 1){ 214 while(GetTop(S,P) && P){ 215 printf("%c ",P->data); 216 Push(S,P->lchild); 217 } 218 PopN(S); 219 if(StackEmpty(S) == 1){ 220 Pop(S,P); 221 Push(S,P->rchild); 222 } 223 } 224 return OK; 225 } 226 227 //先序遍歷(非遞歸方法)(方法2) 228 int PrintTree_Re_T(BiTree T){ 229 SqStack s; 230 InitStack(s); 231 BiTree p; 232 p = T; 233 while(p || StackEmpty(s) == 1){ 234 while(p){ 235 printf("%c ",p->data); 236 Push(s,p); 237 p = p->lchild; 238 } 239 if(StackEmpty(s) == 1){ 240 Pop(s,p); 241 p = p->rchild; 242 } 243 } 244 return OK; 245 } 246 247 //中序遍歷(非遞歸)(方法1) 248 int PrintTreeL_Re(BiTree T){ 249 SqStack S; 250 InitStack(S);//建立棧 251 Push(S,T); //樹的根節點先入棧 252 BiTree P; 253 while(StackEmpty(S) == 1){ 254 while(GetTop(S,P) && P){ 255 Push(S,P->lchild); 256 } 257 PopN(S); 258 if(StackEmpty(S) == 1){ 259 Pop(S,P); 260 printf("%c ",P->data); 261 Push(S,P->rchild); 262 } 263 } 264 return OK; 265 } 266 267 //中序遍歷(非遞歸)(方法2) 268 int PrintTreeL_Re_T(BiTree T){ 269 SqStack S; 270 InitStack(S);//建立棧 271 BiTree P; 272 P = T; 273 while(P || StackEmpty(S) == 1){ 274 if(P){ 275 Push(S,P); 276 P = P->lchild; 277 }else{ 278 Pop(S,P); 279 printf("%c ",P->data); 280 P = P->rchild; 281 } 282 } 283 return OK; 284 } 285 286 //后序遍歷(非遞歸方法) 287 int PrintTreeR_Re(BiTree T){ 288 SqStack s; 289 InitStack(s);//建立棧 290 Push(s,T); //樹的根節點先入棧 291 BiTree p,q; 292 while(StackEmpty(s) == 1){ 293 GetTop(s,p); 294 if((p->lchild == NULL && p->rchild == NULL) || ( q && ( q == p->lchild || q == p->rchild))){ 295 printf("%c ",p->data); 296 PopN(s); 297 q = p; 298 }else{ 299 if(p->rchild){ 300 Push(s,p->rchild); 301 } 302 if(p->lchild){ 303 Push(s,p->lchild); 304 } 305 } 306 } 307 return OK; 308 } 309 310 311 /*層次遍歷二叉樹*/ 312 void HierarchicalTree(BiTree T){ 313 BiTree Ta = T; 314 if(Ta){ 315 printf("%c ",Ta->data); 316 if(Ta->lchild){ 317 //printf("%c ",Ta->lchild->data); 318 HierarchicalTree(Ta->lchild); 319 } 320 if(Ta->rchild){ 321 //printf("%c ",Ta->rchild->data); 322 HierarchicalTree(Ta->rchild); 323 } 324 } 325 } 326 327 /*層次遍歷二叉樹(借助隊列實現)*/ 328 void HierarchicalTree_Q(BiTree T){ 329 LinkQueue Q; 330 InitQueue(Q); //建立隊列 331 EnQueue(Q,T); //樹的根節點先入列 332 BiTree Ta; 333 while(Q.front != Q.rear){ 334 DeQueue(Q,Ta); 335 if(Ta->lchild){ 336 EnQueue(Q,Ta->lchild); 337 } 338 if(Ta->rchild){ 339 EnQueue(Q,Ta->rchild); 340 } 341 printf("%c ",Ta->data); 342 } 343 } 344 345 /*層次遍歷二叉樹(並且分層打印)(借助隊列實現)*/ 346 void HierarchicalTree_DA(BiTree T){ 347 LinkQueue Q; 348 InitQueue(Q);//建立隊列 349 EnQueue(Q,T);//樹的根節點先入列 350 BiTree Ta1,Tb1,Tc1; 351 352 //創建標志位 353 char data[3] = {'*',' ',' '}; 354 CreateBiTree(Ta1,data); 355 356 //創建移動的指針 357 QueuePtr point; 358 point = Q.front->next;//移動指針先指向頭結點 359 EnQueue(Q,Ta1);//插入標志位 360 printf("\n"); 361 while(point){ 362 //判斷左右節點 363 if(point->data->lchild || point->data->rchild){ 364 if(point->data->lchild){ 365 EnQueue(Q,point->data->lchild); 366 } 367 if(point->data->rchild){ 368 EnQueue(Q,point->data->rchild); 369 } 370 } 371 point = point->next; //指針下移一位 372 if(point->data->data == '*'){ 373 if(!point->next){//判斷是否到結尾(到結尾直接退出) 374 break; 375 } 376 EnQueue(Q,Ta1);//插入標志節點 377 point = point->next; //如果遇到標志位,則指針下移 378 } 379 } 380 381 printf("\n"); 382 //循環輸出節點 383 while(Q.front != Q.rear){ 384 DeQueue(Q,Tc1); 385 char str = Tc1->data; 386 if(str == '*'){ 387 printf("\n"); 388 }else{ 389 printf("%c ",str); 390 } 391 } 392 } 393 394 //統計二叉樹節點的個數 395 void getTreeNodeNum(BiTree T,int &num){ 396 if(!T){ 397 num = 0; 398 } 399 num++; 400 if(T->lchild){ 401 getTreeNodeNum(T->lchild,num); 402 } 403 if(T->rchild){ 404 getTreeNodeNum(T->rchild,num); 405 } 406 } 407 408 //得到樹的深度 409 int getTreeHeight(BiTree T){ 410 int hl,hr,max; 411 if(T!=NULL){ 412 hl=getTreeHeight(T->lchild); 413 hr=getTreeHeight(T->rchild); 414 max=hl>hr?hl:hr; 415 return (max+1); 416 }else{ 417 return 0; 418 } 419 } 420 421 //得到第k層的節點個數 422 int getNodeNum(BiTree T, int k){ 423 if (!T || k < 1){ 424 return 0; 425 } 426 if (k == 1){ 427 return 1; 428 } 429 return getNodeNum(T->lchild, k-1) + getNodeNum(T->rchild, k-1); 430 } 431 432 void main(){ 433 i = 0; 434 //char Data[15] = {'A','B','C',' ',' ','D','E',' ','G',' ',' ','F',' ',' ',' '}; 435 //char Data[15] = {'A','B','C',' ',' ','D','E',' ',' ','G',' ',' ','F',' ',' '}; 436 char Data[16] = {'A','B','C',' ',' ',' ','D','E',' ','G',' ',' ','F',' ',' ',' '}; 437 //char Data[7] = {'A','B','C',' ',' ',' ',' '}; 438 //char Data[7] = {'A',' ','b',' ','c',' ',' '}; 439 BiTree Ta,Tb; 440 CreateBiTree(Ta,Data); 441 printf("*****************遞歸方法遍歷二叉樹**************\n"); 442 printf("先序遍歷:"); 443 PrintTree(Ta); 444 445 printf("\n"); 446 printf("中序遍歷:"); 447 PrintTreeL(Ta); 448 449 printf("\n"); 450 printf("后序遍歷:"); 451 PrintTreeR(Ta); 452 printf("\n"); 453 454 printf("非遞歸先序遍歷法1:"); 455 PrintTree_Re(Ta); 456 printf("\n"); 457 458 printf("非遞歸先序遍歷法2:"); 459 PrintTree_Re_T(Ta); 460 printf("\n"); 461 462 printf("非遞歸中序遍歷法1:"); 463 PrintTreeL_Re(Ta); 464 printf("\n"); 465 466 printf("非遞歸中序遍歷法2:"); 467 PrintTreeL_Re_T(Ta); 468 printf("\n"); 469 470 printf("非遞歸后序遍歷:"); 471 PrintTreeR_Re(Ta); 472 printf("\n"); 473 474 printf("層次遍歷:"); 475 HierarchicalTree_Q(Ta); 476 printf("\n"); 477 478 printf("\n"); 479 printf("層次遍歷(分層顯示):"); 480 i = 0; 481 HierarchicalTree_DA(Ta); 482 printf("\n"); 483 484 printf("總結點個數:"); 485 int TreeNum = 0; 486 getTreeNodeNum(Ta,TreeNum); 487 printf("%d ",TreeNum); 488 printf("\n"); 489 490 printf("樹的深度:"); 491 int TreeHeight = 0; 492 TreeHeight = getTreeHeight(Ta); 493 printf("%d ",TreeHeight); 494 printf("\n"); 495 496 printf("得到第3層的節點個數:"); 497 printf("%d",getNodeNum(Ta,3)); 498 printf("\n"); 499 500 }
運行結果:
轉載請注明出處,謝謝!