给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜面反转,再输出反转后的层序遍历的序列。所谓镜面反转,是指将所有非叶结点的左右孩子对换。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N
(≤30),是二叉树中结点的个数。第二行给出其中序遍历序列。第三行给出其前序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树反转后的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
1 2 3 4 5 6 7
4 1 3 2 6 5 7
输出样例:
4 6 1 7 5 3 2
和我印象中的一样,可以暴力的不用正式建树
暴力版
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<set>
#include<vector>
#include<map>
using namespace std;
int in[35],pre[35];
map<int ,int> a;
void test(int l,int r,int ll,int rr,int x)
{
if(l<=r&&ll<=rr)
{
a[x] = pre[ll];
int i=l;
while(i<=r)
{
if(pre[ll]==in[i])
{
test(i+1,r,ll+i-l+1,rr,2*x+1);
test(l,i-1,ll+1,ll+i-l,2*x+2);
return;
}
i++;
}
}
}
int main()
{
int n;
cin>>n;
for(int i = 0; i<n; i++)
cin>>in[i];
for(int i = 0; i<n; i++)
cin>>pre[i];
test(0,n-1,0,n-1,1);
int tmp = 0;
map<int ,int>::iterator it=a.begin();
while(it!=a.end())
{
if(tmp)
cout<<" ";
cout<<it->second;
tmp++;
it++;
}
return 0;
}
建树版
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=100;
struct tree
{
int l,r;
};
tree a[maxn];
int n,mid[maxn],pre[maxn];
void dfs(int x,int y,int len)//x,y分别表示当前二叉树在mid数组和pre数组的首地址,len为其长度
{
if(len<2) return;//三个结点构成一棵完整二叉树, 不够就不用遍历了,return即可
int root=pre[y];//每次pre的首地址对应的数值为当前根结点编号
int pos;//pos为当前根结点在mid数组的位置
for(pos=0;mid[x+pos]!=root;pos++);//找当前根结点在mid数组的位置pos
if(pos!=0){//dfs建立左子树
a[root].l=pre[y+1];//root的左孩子即为pre[y+1](即:左子树的根)
dfs(x,y+1,pos);//左子树在mid和pre的首地址分别为x和y+1,长度为pos
}
if(pos!=len-1){//dfs建立右子树
a[root].r=pre[y+pos+1];//root的右孩子即为pre[y+pos+1](即:右子树的根)
dfs(x+pos+1,y+pos+1,len-pos-1);//右子树在mid和pre的首地址分别为x+pos+1和y+pos+1,长度为len-pos-1
}
}
queue<int>q;
void bfs()
{
q.push(pre[0]);
while(!q.empty()){
int p=q.front();
q.pop();
if(p!=pre[0]){
cout<<" ";
}
cout<<p;
if(a[p].r){
q.push(a[p].r);
}
if(a[p].l){
q.push(a[p].l);
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n;
for(int i=0;i<n;i++) cin>>mid[i];
for(int i=0;i<n;i++) cin>>pre[i];
dfs(0,0,n);
bfs();
return 0;
}