这题考察由中序序列和后序序列创建一棵二叉树。
由中序序列可以得知当前结点(即根)的左右儿子的大小。
由于后序遍历的排列方式是左右根,而左右边界都已知,因此只需要知道左儿子大小即可,其值等于在中序序列中根位置减左边界位置。
根位置可以事先对中序序列做映射得到。
所以在递归创建左右子树的时候,除了传入后序序列中的左右边界,还要传入左边界在中序序列中的位置。其值只能通过上一层获得。对于左子树在上一层直接传入左边界,对于右子树在上一层传入中序根位置+1
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define MX 40
struct node{
int left, right;
};
int main(){
int n;
cin >> n;
vector<node> a(MX);
vector<int> v(n), mp(MX);
for (int i = 0; i < n;++i)
cin >> v[i];
for (int i = 0; i < n;++i){
int x;
cin >> x;
mp[x] = i;
}
function<int(int, int, int)> solve = [&](int l, int r, int ilst)->int
{
if(l>r)
return -1;
int root = r;
int val = v[root]; //val : 根的值
int ipos = mp[val]; // ipos : 根在中序序列中的位置
int lsize = ipos - ilst; // lsize : 左儿子的度
// ilst : 左儿子在中序序列中的位置
a[val].left = solve(l, l + lsize-1, ilst);
a[val].right = solve(l + lsize, r - 1, ipos + 1);
return val;
};
solve(0, n - 1, 0);
vector<int> ans;
queue<int> q;
q.push(v[n - 1]);
while(!q.empty()){
int x = q.front();
q.pop();
ans.push_back(x);
if(a[x].left!=-1)
q.push(a[x].left);
if(a[x].right!=-1)
q.push(a[x].right);
}
for (int i = 0; i < n;++i){
cout << ans[i] << " \n"[i == n - 1];
}
return 0;
}