原题来自维基OI
题目描述:给出一个二叉树,输出它的最大宽度和高度.
输入描述:第一行一个整数n.下面n行每行有两个数,对于第i行的两个数,代表编号为i的节点所连接的两个左右儿子的编号.如果没有某个儿子为空,则为0.
输出描述:输出一共三行,分别为前序遍历,中序遍历和后序遍历.编号之间用空格隔开.
说明:默认结点1是根节点,根节点的高度为1.
大概思路:高度就是最下方结点的层数,宽度就是层结点数最多层的结点数.
以这棵树为例,高度就是最下方结点(绿色结点)的层数,也就是4;宽度就是层结点数最多层(第4层)的结点数.
第一步:用一个多维数组tree[21][4]来储存这棵树,tree[n][0]为结点n的左子树,[n][1]为结点n的右子树,[n][2]为结点n的父亲,[n][3]为结点n所在层数.
根据输入描述,第i个结点的左儿子和右儿子都是在第i行读入的,当读入第i行时,如果有左儿子就把左儿子的父亲设为i,右儿子同理.
第二步:把tree[1][3]设为1,因为默认结点1高度为1.因为每个非根结点所在的层数是它父亲所在层数+1,代码表示:tree[i][3]=tree[tree[i][2]][3]+1;
递推算出每1层的层数,算出层数的同时直接寻找最大值.
第三步:在第二步执行过程中,如果碰到一个结点属于第i层,那么layer[i]+1(初始每个元素都为0),到第二步执行完成,就寻找layer中的最大值,最大值的下标就是宽度.
AC代码如下:
1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 int tree[21][4];/* 二维数组tree,储存了输入的二叉树 */ 7 /* tree[n][0]为结点n的左子树,[n][1]为结点n的右子树,[n][2]为结点n的父亲,[n][3]为结点n所在层数 */ 8 int layer[20];/* 层数数组,layer[i]就是第i层的结点数,也就是第i层的宽度 */ 9 int findmax()/* 找到layer中的最大值,也就是也就是最大宽度 */ 10 { 11 int maxmium = -1; 12 for (int i = 1; i < sizeof(layer)/sizeof(layer[0]); i++) 13 { 14 if (layer[i]>maxmium) 15 { 16 maxmium=layer[i]; 17 } 18 } 19 return maxmium; 20 } 21 int main() 22 { 23 int n,depth=1; 24 cin >> n; 25 memset(layer,sizeof(layer),0); 26 for (int i = 1; i <= n; i++) 27 { 28 cin >> tree[i][0] >> tree[i][1];/* 读入二叉树 */ 29 if (tree[i][0] != 0) 30 { 31 tree[tree[i][0]][2] = i;/* 设置父亲 */ 32 } 33 if (tree[i][1] != 0) 34 { 35 tree[tree[i][1]][2] = i;/* 设置父亲 */ 36 } 37 } 38 tree[1][3] = 1;/* 根结点的层数默认为1 */ 39 layer[1]=1;/* 第一层的宽度一定为1 */ 40 for (int i = 2; i <= n; i++) 41 { 42 tree[i][3] = tree[tree[i][2]][3] + 1;/* 第i个结点的层数是它父亲的层数+1,递推 */ 43 layer[tree[i][3]]++;/* 第i个结点所属的层数+1,统计每层的节点数 */ 44 if (tree[i][3] > depth) 45 { 46 depth = tree[i][3];/* 设置层数的同时直接比较高度(高度即层数) */ 47 } 48 } 49 cout << findmax() << ' ' << depth;/* 输出 */ 50 return 0; 51 }
如果有什么不合理之处,敬请批评指正