树的孩子兄弟储存法及其上部分操作
写这个博客的原因很单纯,武大的考研真题的代码题遇见了,然后衍生出一大堆的问题。为了确保考试的时候万无一失,还是自己亲自动手把最靠谱的代码写出来,做个记录。
简单说一下树,它的定义是一个递归定义,那么这个特性也就很容易让它和递归函数相结合来解决一些实际问题。
准备了一棵树,然后右边对应的是它的孩子兄弟表示法做成的二叉树
(用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; }
posted on 2016-11-13 23:07 tianxia2s 阅读(1923) 评论(2) 编辑 收藏 举报