题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805069361299456
思路:后序遍历的最后一个值是树根,再在中序遍历中找到树根的位置,就可以求出左子树的长度,将左子树的长度用到后序遍历中就可以清楚地划分后序遍历的左子树、右子树、根的位置范围,由此不断迭代
#include<bits/stdc++.h>
using namespace std;
struct node
{
int l,r;
};
int hx[35];
int zx[35];
node tree[55];
int build(int hl,int hr,int zl,int zr)
{//hl、hr分别为后序遍历的左边界和右边界,zl、zr分别为中序遍历的左边界和右边界
if(zl>zr) return 0; //如果左边界大于右边界,结束
int rt=hx[hr]; //取根节点的值
int pos=zl; //根节点在中序遍历中的位置,先初始化为中序遍历的左边界
while(zx[pos]!=rt) pos++; //找到根节点在中序遍历中的位置
int len=pos-zl; //求出左子树的长度
tree[rt].l=build(hl,hl+len-1,zl,pos-1); //建左子树
tree[rt].r=build(hl+len,hr-1,pos+1,zr); //建右子树
return rt; //返回根节点
}
void bfs(int root)
{
int rt;
queue<int>que; //存放树节点的队列
vector<int>v; //前序遍历的数组
que.push(root); //存入根节点
while(!que.empty()) //队列不为空
{
rt=que.front(); //取出根节点
que.pop();
if(rt==0) continue; //如果根为空,则结束此分支的迭代
v.push_back(rt); //存入前序遍历的数组
if(tree[rt].l!=0) que.push(tree[rt].l); //遍历左子树
if(tree[rt].r!=0) que.push(tree[rt].r); //遍历右子树
}
int len=v.size();
for(int i=0;i<len;i++) //输出前序遍历
{
if(i==0) cout<<v[i];
else cout<<" "<<v[i];
}
cout<<endl;
}
int main()
{
int n;
while(cin>>n)
{
for(int i=0;i<n;i++) cin>>hx[i]; //输入后序遍历
for(int i=0;i<n;i++) cin>>zx[i]; //输入中序遍历
int root=build(0,n-1,0,n-1); //建树
bfs(root); //输出前序遍历
}
return 0;
}