紫书例题:The Falling Leaves,(UVa 699)
给一颗二叉树,每个结点都有一个水平位置:左子结点在它左边1个单位,右子结点在右边一个单位,从左向右输出每个水平位置的所有结点权值之和。如样例所示,从左到右的3个位置的权和分别为7,11,3。按照递归(先序)输入,用-1表示空树。
5 8
/ \ / \
7 3 2 3
\ / \ /
6 9 (6+7)
结果: 7 11 3 / \
5 12
结果: 9 7 21 15
样例输入:
5 7 -1 6 -1 -1 3 -1 -1
8 2 9 -1 -1 6 5 -1 -1 12 -1 -1 3 7 -1 -1 -1
-1
样例输出:
Case 1:
7 11 3
Case 2:
9 7 21 15
对树的形态和递归创建都没有什么疑问,关键是这水平方向上怎么对齐啊?
Case 1中,结点7的右孩子6怎么就对到结点5上去了呢?
Case 2中,为毛结点2的右子结点6,和结点3的左子结点7堆叠到了同一水平位置上??
为毛结点6的右子结点5要和结点2对齐???
后来调试原书发现,如果根节点是水平位置是n,那么左孩子为n-1,右孩子为n+1,这样一些同层的节点就堆叠到一个水平面上了
根(n)
/ \
左(n-1) 右(n+1)
8(n)
/ \
2(n-1) 3(n+1)
/ \ /
9(n-2) 6(n) 7(n)
/ \
5(n-1) 12(n+1)
源代码:
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 100 ;
int sum[maxn] ;
void buildtree(int val,int p) //建树,p为树根的水平位置
{
int vl;
if(val == -1) return ;
sum[p] += val ;
cin >> vl ;
buildtree(vl,p - 1);
cin >> vl ;
buildtree(vl,p + 1);
}
int main()
{
int k=0,v;
while(cin >> v && v != -1){
int pos = maxn/2 ;
buildtree(v,pos) ;
int p = 0;
while(sum[p] == 0) p++ ; //最左边的子叶
cout << "Case " << ++k << ":\n" << sum[p++];
while(sum[p] != 0) {
cout << " " << sum[p];
p++;
}
cout << "\n\n";
}
return 0;
}