标签:
题意:给出一颗点带权的二叉树的中序和后序遍历,找一个叶子使得它到根的路径上的权和最小。
学习的紫书:先将这一棵二叉树建立出来,然后搜索一次找出这样的叶子结点
虽然紫书的思路很清晰= =可是理解起来好困难啊啊啊啊
后来终于问懂一丢丢了---
比如说样例:
中序遍历:3 2 1 4 5 7 6
后序遍历:3 1 2 5 6 7 4
首先做第一层: 在后序遍历中的最后一个数为根节点,然后在到中序遍历中找到这个根节点,在这个根节点的左边是左子树,右边是右子树,这样就确定出了左子树和右子树的区间
然后做第二层 中序遍历左子树的长度等于后序遍历中左子树的长度 即为在这个样例中:
中序遍历的左子树为 3 2 1 后序遍历的左子树为3 1 2 然后又可以确定2为这颗左子树的一个根节点,又可以将 3 2 1划分成左右子树区间
就这样一层一层划分建树
概括一下就是:
中序遍历序列:【左子树区间中序遍历序列】【根】【右子树区间中序遍历序列】
后序遍历序列:【左子树区间中序遍历序列】【右子树区间中序遍历序列】【根】
话说build函数也理解了好久的说 = =
对于lch[root]=build(L1,p-1,L2,L2+cnt-1);L1到p-1是在中序遍历中的左子树 L2到L2+cnt-1是在后序遍历中的左子树
对于rch[root]=build(p+1,R1,L2+cnt,R2-1);p+1到R1是在中序遍历中的右子树
L2+cnt到R2-1是在后序遍历中的右子树
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include<algorithm> 6 #include<sstream> 7 using namespace std; 8 9 typedef long long LL; 10 const int maxn=10000+5; 11 int in_order[maxn],post_order[maxn],lch[maxn],rch[maxn]; 12 int n; 13 14 bool read_list(int *a){ 15 string line; 16 if(!getline(cin,line)) return false; 17 stringstream ss (line); 18 n=0; 19 int x; 20 while(ss>>x) a[n++]=x; 21 return n>0; 22 } 23 24 int build(int L1,int R1,int L2,int R2){ 25 if(L1>R1) return 0; 26 int root=post_order[R2]; 27 int p=L1; 28 while(in_order[p]!=root) p++; 29 int cnt=p-L1;//左子树的结点个数 30 lch[root]=build(L1,p-1,L2,L2+cnt-1); 31 rch[root]=build(p+1,R1,L2+cnt,R2-1); 32 return root; 33 } 34 35 int best,best_sum; 36 37 void dfs(int u,int sum){ 38 sum+=u; 39 if(!lch[u]&&!rch[u]){ 40 if(sum<best_sum||(sum==best_sum&&u<best)) { 41 best=u; 42 best_sum=sum; 43 } 44 } 45 46 if(lch[u]) dfs(lch[u],sum);//如果u有左孩子,继续深搜,直到搜到叶子结点 47 if(rch[u]) dfs(rch[u],sum); 48 } 49 50 int main(){ 51 while(read_list(in_order)){ 52 read_list(post_order); 53 build(0,n-1,0,n-1); 54 best_sum=1000000005; 55 dfs(post_order[n-1],0); 56 cout<<best<<"\n"; 57 } 58 return 0; 59 }
go---go---
标签:
原文地址:http://www.cnblogs.com/wuyuewoniu/p/4331052.html