紫书题解1.下落的树叶(UVa 699 深广度)

紫书例题: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;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值