寫這個博客的原因很單純,武大的考研真題的代碼題遇見了,然后衍生出一大堆的問題。為了確保考試的時候萬無一失,還是自己親自動手把最靠譜的代碼寫出來,做個記錄。
簡單說一下樹,它的定義是一個遞歸定義,那么這個特性也就很容易讓它和遞歸函數相結合來解決一些實際問題。
准備了一棵樹,然后右邊對應的是它的孩子兄弟表示法做成的二叉樹
(用word畫的,有點丑,多體諒)
下面是提出問題:
提供樹的孩子兄弟表示法的二叉樹存儲結構,二叉樹的頭結點指針為struct BTree *head;通過代碼實現求出:
1)求出樹的度(樹中每個節點的出度的最大值);
2)求出樹中葉子節點的個數;
3)求出樹的高度。
那么首先是說說我自己的思想:
對於問題一,這個是武漢大學研究生考試的一個代碼題,分數20分,試卷里邊算是最難的一個了。第一次寫我自己用的是遞歸的方法,然后問題想的不全面,算是錯了。第二天回想的時候想起來采用類似於堆排序或者說是快速排序的方式,將問題分為兩個部分來看待,采用遞推的方式實現,整個思路清晰了很多。
第一步:構建函數int CountMaxOut(struct BTree* p); 函數功能是求出p對應的節點的出度數,實現方法是判斷是否有左孩子?沒有出度為0,有的話設置一個count=1,然后計算左孩子遞推下去有幾個右孩子,返回count; 第二步:設置一個MaxCount,每次更新count的最大值; 第三步:遍歷二叉樹(先序遍歷,中序遍歷和后續變量選個你喜歡的就好了,每次訪問節點的信息部分更改為調用第一步的函數,計算對應的出度數,並更新最大值) 第四步:返回結果,解決問題
完整運行代碼:

1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define MAX 100 5 6 char * p; 7 typedef struct BTree{ 8 char str; 9 struct BTree * lchild; 10 struct BTree * rchild; 11 }BTree; 12 13 BTree* creat_tree(){ 14 BTree* temp; 15 while(*p==' ')p++; 16 if(*p=='#'){ 17 p++; 18 return NULL; 19 } 20 if(*p!=' '){ 21 temp = (BTree *)malloc(sizeof(BTree)); 22 temp->str=*p++; 23 temp->lchild=creat_tree(); 24 temp->rchild=creat_tree(); 25 } 26 return temp; 27 } 28 29 void pre_visit(BTree* node){ 30 printf("%c",node->str); 31 if(node->lchild!=NULL)pre_visit(node->lchild); 32 if(node->rchild!=NULL)pre_visit(node->rchild); 33 } 34 35 int count_node(BTree * node){ 36 int count=1; 37 38 if(node==NULL||node->lchild==NULL)return 0; 39 else{ 40 BTree *temp=node->lchild; 41 while(temp->rchild!=NULL){count++;temp=temp->rchild;} 42 } 43 44 return count; 45 } 46 47 int pre_visit_count(BTree* node){ 48 if(node==NULL)return 0; 49 int count1=count_node(node); 50 int count2,count3,max; 51 count2=count3=0; 52 53 if(node->lchild!=NULL)count2=pre_visit_count(node->lchild); 54 if(node->rchild!=NULL)count3=pre_visit_count(node->rchild); 55 max=count1>count2?count1:count2; 56 max=max>count3?max:count3; 57 return max; 58 } 59 60 int main() 61 { 62 char tree[MAX];p=tree; 63 BTree * head; 64 printf("Please input the tree(use char and #)\n要求按照先序遍歷的方式輸入,加上#進行區分\n例如123# #4##5##:\n"); 65 //scanf("%s",tree); 66 gets(tree); 67 68 if(*p!='\0'&&*p!=' '&&*p!='#'){ 69 head=(BTree *)malloc(sizeof(BTree)); 70 head->str=*p++; 71 //printf("head is %c",head->str); 72 head->lchild=creat_tree(); 73 head->rchild=creat_tree(); 74 } 75 76 printf("tree is :\n"); 77 pre_visit(head); 78 79 //在二叉樹構造出來的前提下,開始處理孩子兄弟表示法 80 //問題一:求出使用孩子兄弟表示法的樹的度 81 printf("那么在前邊我設置了兩個函數,一個用來計算每個節點的度,另一個用來計算所有度中的最大值\n"); 82 printf("測試用例124#5#6##3###\n"); 83 printf("二叉樹對應的樹的度為:%d",pre_visit_count(head)); 84 return 0; 85 }
關聯代碼
int count_node(BTree * node){ int count=1; if(node==NULL||node->lchild==NULL)return 0; else{ BTree *temp=node->lchild; while(temp->rchild!=NULL){count++;temp=temp->rchild;} } return count; } int pre_visit_count(BTree* node){ if(node==NULL)return 0; int count1=count_node(node); int count2,count3,max; count2=count3=0; if(node->lchild!=NULL)count2=pre_visit_count(node->lchild); if(node->rchild!=NULL)count3=pre_visit_count(node->rchild); max=count1>count2?count1:count2; max=max>count3?max:count3; return max; }
對於問題二 ,這是一個衍生題。確實很奇怪,考研書籍對這個問題研究的很少,但是我感覺這個題目真的是一個純粹的二叉樹的遍歷問題,這么好的價值沒有被發掘出來?
問題分析: 樹的葉子節點也就是沒有孩子節點,在二叉樹中的體現就是左孩子為空。 問題就抓化的很簡單了——>求出二叉樹中左孩子為空的節點的數量。 二叉樹的遍歷,同時判斷if(p——>lchild==NULL)count++;' 最后輸出count就OK了,同樣,代碼晚些貼出來
完整代碼

#include <stdio.h> #include <stdlib.h> #define MAX 100 char * p; typedef struct BTree{ char str; struct BTree * lchild; struct BTree * rchild; }BTree; BTree* creat_tree(){ BTree* temp; while(*p==' ')p++; if(*p=='#'){ p++; return NULL; } if(*p!=' '){ temp = (BTree *)malloc(sizeof(BTree)); temp->str=*p++; temp->lchild=creat_tree(); temp->rchild=creat_tree(); } return temp; } void pre_visit(BTree* node){ printf("%c",node->str); if(node->lchild!=NULL)pre_visit(node->lchild); if(node->rchild!=NULL)pre_visit(node->rchild); } int count_node(BTree * node){ int count=1; if(node==NULL||node->lchild==NULL)return 0; else{ BTree *temp=node->lchild; while(temp->rchild!=NULL){count++;temp=temp->rchild;} } return count; } int pre_visit_count(BTree* node){ if(node==NULL)return 0; int count1=count_node(node); int count2,count3,max; count2=count3=0; if(node->lchild!=NULL)count2=pre_visit_count(node->lchild); if(node->rchild!=NULL)count3=pre_visit_count(node->rchild); max=count1>count2?count1:count2; max=max>count3?max:count3; return max; } int count_leaf(BTree* node){ int count = 0; if (node->lchild==NULL)count++; if(node->lchild!=NULL)count+=count_leaf(node->lchild); if(node->rchild!=NULL)count+=count_leaf(node->rchild); return count; } int main() { char tree[MAX];p=tree; BTree * head; printf("Please input the tree(use char and #)\n要求按照先序遍歷的方式輸入,加上#進行區分\n例如123# #4##5##:\n"); //scanf("%s",tree); gets(tree); if(*p!='\0'&&*p!=' '&&*p!='#'){ head=(BTree *)malloc(sizeof(BTree)); head->str=*p++; //printf("head is %c",head->str); head->lchild=creat_tree(); head->rchild=creat_tree(); } printf("tree is :\n"); pre_visit(head); //在二叉樹構造出來的前提下,開始處理孩子兄弟表示法 //問題一:求出使用孩子兄弟表示法的樹的度 printf("那么在前邊我設置了兩個函數,一個用來計算每個節點的度,另一個用來計算所有度中的最大值\n"); printf("測試用例124#5#6##3###\n"); printf("二叉樹對應的樹的度為:%d",pre_visit_count(head)); printf("\n樹中葉子節點的數量是:\n"); printf("%d",count_leaf(head)); ; return 0; }
關聯代碼:
int count_leaf(BTree* node){ int count = 0; if (node->lchild==NULL)count++; if(node->lchild!=NULL)count+=count_leaf(node->lchild); if(node->rchild!=NULL)count+=count_leaf(node->rchild); return count; }
對於問題三:我是真的沒把遞推的方法想出來,函數遞歸也是變得相對簡單了。
相關代碼
int height(BTree* node){ int maxh=0,theight,count; if(node==NULL)return 0; if(node->lchild==NULL)return 1; BTree *temp=node->lchild; while(temp!=NULL){ maxh=(maxh>(count=height(temp))?maxh:count); temp=temp->rchild; } theight=1+maxh; return theight; }
完整代碼
#include <stdio.h> #include <stdlib.h> #define MAX 100 char * p; typedef struct BTree{ char str; struct BTree * lchild; struct BTree * rchild; }BTree; BTree* creat_tree(){ BTree* temp; while(*p==' ')p++; if(*p=='#'){ p++; return NULL; } if(*p!=' '){ temp = (BTree *)malloc(sizeof(BTree)); temp->str=*p++; temp->lchild=creat_tree(); temp->rchild=creat_tree(); } return temp; } void pre_visit(BTree* node){ printf("%c",node->str); if(node->lchild!=NULL)pre_visit(node->lchild); if(node->rchild!=NULL)pre_visit(node->rchild); } int count_node(BTree * node){ int count=1; if(node==NULL||node->lchild==NULL)return 0; else{ BTree *temp=node->lchild; while(temp->rchild!=NULL){count++;temp=temp->rchild;} } return count; } int pre_visit_count(BTree* node){ if(node==NULL)return 0; int count1=count_node(node); int count2,count3,max; count2=count3=0; if(node->lchild!=NULL)count2=pre_visit_count(node->lchild); if(node->rchild!=NULL)count3=pre_visit_count(node->rchild); max=count1>count2?count1:count2; max=max>count3?max:count3; return max; } int count_leaf(BTree* node){ int count = 0; if (node->lchild==NULL)count++; if(node->lchild!=NULL)count+=count_leaf(node->lchild); if(node->rchild!=NULL)count+=count_leaf(node->rchild); return count; } int height(BTree* node){ int maxh=0,theight,count; if(node==NULL)return 0; if(node->lchild==NULL)return 1; BTree *temp=node->lchild; while(temp!=NULL){ maxh=(maxh>(count=height(temp))?maxh:count); temp=temp->rchild; } theight=1+maxh; return theight; } int main() { char tree[MAX];p=tree; BTree * head; printf("Please input the tree(use char and #)\n要求按照先序遍歷的方式輸入,加上#進行區分\n例如123# #4##5##:\n"); //scanf("%s",tree); gets(tree); if(*p!='\0'&&*p!=' '&&*p!='#'){ head=(BTree *)malloc(sizeof(BTree)); head->str=*p++; //printf("head is %c",head->str); head->lchild=creat_tree(); head->rchild=creat_tree(); } printf("tree is :\n"); pre_visit(head); //在二叉樹構造出來的前提下,開始處理孩子兄弟表示法 //問題一:求出使用孩子兄弟表示法的樹的度 printf("那么在前邊我設置了兩個函數,一個用來計算每個節點的度,另一個用來計算所有度中的最大值\n"); printf("測試用例124#5#6##3###\n"); printf("二叉樹對應的樹的度為:%d",pre_visit_count(head)); printf("\n樹中葉子節點的數量是:\n"); printf("%d",count_leaf(head)); printf("\n樹的高度為:\n"); printf("%d",height(head)); return 0; }