面試常考之二叉樹


二叉樹在數據結構面試中的地位舉足輕重,算得上是大公司面試必問,筆試必考;因為對二叉樹的操作直接反應一個人的數據結構功底有多深厚,基礎知識是否扎實。。。(一點廢話),下面就二叉樹的基本操作說一說二叉樹的知識點,不對之處還請指正。

面試常考的幾個操作:

1:二叉樹的基本性質

2:遞歸建立二叉樹

3:遞歸遍歷二叉樹(先序,中序,后序)

4:非遞歸遍歷二叉樹(先序,中序,后序)

5:求二叉樹中的節點個數

6:求二叉樹的深度

7:分層遍歷二叉樹

8:求二叉樹第K層的節點個數

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;

 

1:二叉樹的基本性質 

一、二叉樹第 i 層上最多有2i-1個節點

二、深度為 k 的二叉樹,最多有2k - 1個節點

三、對於任意一顆二叉樹T,如果其終端節點數為n1度數為2的節點數為n2 則 n1 = n2 + 1;

四、具有n個節點的完全二叉樹深度為[ log2n] + 1;

 

2:遞歸建立二叉樹

遞歸常見二叉樹,先從左子樹開始,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;
}

 

3:遞歸遍歷二叉樹(先序,中序,后序)

這是三中常規的遍歷二叉樹的方法,用的非常多,不僅便於理解,而且三個函數只是調用順序不同,所以書上頁數先給出了這三種遍歷。當然在面試中也長問到。

 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 }

 

4:非遞歸遍歷二叉樹(先序,中序,后序)

非遞歸遍歷在面試中問的非常多,特別是大公司的面試,幾乎是必問,所以這里就非遞歸的方法每個給出了兩種

一、先序遍歷:

  先序遍歷這里給出了兩個方法,兩種方法都是借助於棧來實現,具體的棧的操作在最后源程序中都有,看家可以看看,非遞歸的操作比遞歸麻煩得多,第一種方法是:首先根節點入棧,然后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 }

 

5:求二叉樹中的節點個數

其實就是遍歷一遍二叉樹,不再多說,看程序便知

 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 }

 

6:求二叉樹的深度

思想就是從左子樹開始遍歷,遞歸完整個樹結構,如果二叉樹不為空,二叉樹的深度 = 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 }

 

7:分層遍歷二叉樹

一、樹的層次結構分層打印與隊列的的先進先出相似,所以我選擇用隊列來完成,首先根節點入隊列,然后左孩子,又孩子以此入隊列,打印即可

 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 }

 

8:求二叉樹第K層的節點個數

利用遞歸的次數來(孩子節點不為空的條件)來簡介得到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 }

 

9:求二叉樹的鏡像

所謂的鏡像其實就是左子樹和右子樹互換顛倒,如下面代碼。

 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 }

 

10:測試源碼

最后附上完整的測試代碼,其中包含了,隊列的初始化,插入隊列,出隊列操作,棧的初始化,進棧,出棧,得到棧頂元,樹的初始化素等也可以復習一下。中間可定有不對不足的地方,還望大神們多多指正

  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 }

 

運行結果:

 

轉載請注明出處,謝謝!

 


免責聲明!

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



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