递归遍历树还是有点绕。现在看来是这样
1.先序遍历的结果,第一个为节点,然后一坨是PreOrder(left[root])的结果,右边是PreOrder(right[root])的结果
2.中序遍历,同理,节点在中间。
3.后序遍历,同理,节点在最后
在这道题中,因为要区分节点,所以每个节点权值不一样,所以可以用节点的权值来唯一表征节点。总的来说:
1.用数组实现了树,left[root]是root左边的权值,right[root]是root右边的权值。
2.build函数写的很好,l1和r1代表了构建树所需要的inorder的范围,包括InOrder(left[root]),root,InOrder(right[root])。l2和r2代表了构建树所需要的PostOrder的范围。我们要做的事情,就是把利用PostOrder来把root找到,然后在InOrder中分出左边和右边,在进行下一次构建。而这个递归的出口条件,就是范围为0,即l1>r1. 因为build是返回所需构建范围中的结点,所以当终值的时候,返回0,即0即为接地。这就要满足不存在零权值的节点了。
3.更多的细节,比如读入数据,边界是多少,还需要更加熟悉。
下面上代码,还需要更熟悉一下。
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>
using namespace std;
const int maxn=10010;
int in_order[maxn],post_order[maxn],lef[maxn],righ[maxn];
int n;
bool read_list(int *a){
string line;
if(!getline(cin,line))//模板
return false;
stringstream ss(line);
n=0;
int x;
while(ss>>x)
{
a[n++]=x;
}
return true;
}
int build(int l1,int r1,int l2,int r2){
if(l1>r1)
return 0;
int root=post_order[r2];
int p=l1;
while(in_order[p]!=root)
p++;
int ct=p-l1;
lef[root]=build(l1,p-1,l2,l2+ct-1);//
righ[root]=build(p+1,r1,l2+ct,r2-1);
return root;
}
int best,best_sum;
void dfs(int root,int sum){
sum+=root;
if(!lef[root]&&!righ[root]){
if((sum<best_sum)||(sum==best_sum&&root<best)){
best=root;
best_sum=sum;
}
}
if(lef[root]) dfs(lef[root],sum);
if(righ[root]) dfs(righ[root],sum);
}
int main(void){
while(read_list(in_order)){
read_list(post_order);
best_sum=1000000;
int op=build(0,n-1,0,n-1);
dfs(op,0);
cout<<best<<endl;
}
return 0;
}