The Falling Leaves |
Each year, fall in the North Central region is accompanied by the brilliant colors of the leaves on the trees, followed quickly by the falling leaves accumulating under the trees. If the same thing happened to binary trees, how large would the piles of leaves become?
We assume each node in a binary tree "drops" a number of leaves equal to the integer value stored in that node. We also assume that these leaves drop vertically to the ground (thankfully, there's no wind to blow them around). Finally, we assume that the nodes are positioned horizontally in such a manner that the left and right children of a node are exactly one unit to the left and one unit to the right, respectively, of their parent. Consider the following tree:
The nodes containing 5 and 6 have the same horizontal position (with different vertical positions, of course). The node containing 7 is one unit to the left of those containing 5 and 6, and the node containing 3 is one unit to their right. When the "leaves" drop from these nodes, three piles are created: the leftmost one contains 7 leaves (from the leftmost node), the next contains 11 (from the nodes containing 5 and 6), and the rightmost pile contains 3. (While it is true that only leaf nodes in a tree would logically have leaves, we ignore that in this problem.)
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
题意:把在同一垂直线上的树中的结点定义为一个落叶堆,要求求出各个堆上的结点值之和。
关键点1:关键在看懂输入案例,有可能多个行才代表一颗树,输入以-1结束。所以,问题的关键在于把一棵树从输入中区分出来。如何才能把一颗树区分出来了呢?使用一个栈,每输入一个元素先入栈,然后判断输入的值是否为-1,若是从栈中弹出两个元素,若这两个元素都是-1代表当前这个子树结束了,再把它的根结点弹出来,把-1压栈,循环这个操作即可。
关键点2:如何计算各个垂直线上的结点之和?我们可以假设根结点的垂值线坐标为width=0,那么其左子树根结点的坐标为width-1,右子树根结点的坐标为width+1,子树同理...这里其实就树的前序递归遍历的变体
代码:
#include <iostream> #include <vector> #include <stack> #include <map> using namespace std; void leaf_heap(map<int,int> &m,vector<int> &v,int n,int &cur,int width) { if(cur>=n || v[cur]==-1 ){ return ; } m[width]+=v[cur]; leaf_heap(m,v,n,++cur,width-1); leaf_heap(m,v,n,++cur,width+1); } int main() { stack<int > stk; vector<int> v;//存储树的输入序列 int value; int case_num=0; bool fisrt=true,tree_end=false;; while(cin>>value){ if(value==-1 && fisrt) break;//第一个,而且值为-1,输入结束 else { fisrt=false; } v.push_back(value); stk.push(value); while(value==-1 && !stk.empty()){ if(stk.size()==1 && stk.top()==-1){//一棵树结束了 ++case_num; fisrt=true; tree_end=true; break; } int x=stk.top();stk.pop(); int y=stk.top();stk.pop(); if(x==y && x==-1) {//一个子树结束了 stk.pop(); stk.push(-1); }else if(y!=-1){ stk.push(y); stk.push(x); break; } } if(tree_end){//一颗树的输入结束 map<int,int> m; int cur=0,width=0; leaf_heap(m,v,v.size(),cur,width); cout<<"Case "<<case_num<<":"<<endl; bool first=true; for(auto p:m){ if(first){ cout<<p.second; first=false; }else{ cout<<" "<<p.second; } } cout<<endl; cout<<endl; stk.pop(); v.clear(); tree_end=false; } } return 0; }