链接:https://vjudge.net/problem/Aizu-ALDS1_7_D
思路
《挑战程序设计竞赛2:算法与数据结构》一书上第163页的练习题。
根据树的先序序列和中序序列输出后序序列,不少人会想:这不很简单,我把树重建出来然后跑一遍后序不就完事了?
这就太过于平凡,就不太符合我的气质[doge],所以这里我们看一下如何直接根据先序序列和和中序序列构建后序序列。
关键函数来了:
int findmid(int m) //找到m在中序序列中的位置
{
for(int i=0;i<n;i++)
if(midden[i]==m)
return i;
}
void rebuildfront(int l,int r)
{
if(l>r)
return;
int m=pre[pos++];
int x=findmid(m);
rebuildfront(l,x-1);
rebuildfront(x+1,r);
s.push_back(m);
}
原理就是:每次依据前序序列的元素将中序序列分成两部分,再结合三种序列的性质做处理。
其实我也不太好解释,这里建议采用最原始的方法:手动模拟一个数据的过程。
我也是通过模拟之后才知道的,而且还研究出如何通过后序和中序构建前序:
vector<int>s;
int findmid(int m)
{
for(int i=0;i<n;i++)
if(midden[i]==m)
return i;
}
void rebuildfront(int l,int r,int pos)
{
if(l>r)
return;
int m=post[pos];
int x=findmid(m);
s.push_back(m);
rebuildfront(l,x-1,pos-r+x-1);
rebuildfront(x+1,r,pos-1);
}
这里还得自己研究。
伊丽莎白,放一下代码!
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+500;
int midden[maxn],pre[maxn];
int n,pos;
vector<int>s;
int findmid(int m)
{
for(int i=0;i<n;i++)
if(midden[i]==m)
return i;
}
void rebuildfront(int l,int r)
{
if(l>r)
return;
int m=pre[pos++];
int x=findmid(m);
rebuildfront(l,x-1);
rebuildfront(x+1,r);
s.push_back(m);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
cin>>pre[i];
for(int i=0;i<n;i++)
cin>>midden[i];
pos=0;
rebuildfront(0,n-1);
for(int i=0;i<n;i++)
{
if(i)
cout<<' ';
cout<<s[i];
}
cout<<endl;
}
认真系列×3!