Date:2022.04.19
题意描述:
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数N(≤30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
输出格式:
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
输入样例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
输出样例:
4 1 6 3 5 7 2
思路:二叉树中,给出中序+前序/后序中任意个都能唯一确定这棵二叉树。因此这种题在每个递归中都以根为分界点,因此首要目标即找根。以这道题为例:
后序:2 3 1 5 7 6 4 设数组为post[N]
中序:1 2 3 4 5 6 7 设数组为in[N]
因此第一层递归中,根必然为4,那么4可将树分为两类(由于中序是“左根右”,因此4左边为左子树、4右面为右子树),因此根据中序中左右子树的区间(这个区间必定是连续的),可找到后序遍历下的左右子树,从而进入下一层递归。因此我们需要四个变量:
①lll:后序遍历下区间的左端点。
②rrr:后序遍历下区间的右端点。
③iii:后续遍历区间 所对应的 中序遍历区间的左端点。
④jjj:后续遍历区间 所对应的 中序遍历区间的右端点。
这样可能比较抽象,我们解读一下样例:
在第一次递归中,post[l]=2、post[r]=4;in[i]=1、in[j]=7;post[l]=2、post[r]=4;in[i]=1、in[j]=7;post[l]=2、post[r]=4;in[i]=1、in[j]=7;
第一次递归找到的根是4,因此下一层递归的两个区间分别是:
post[l]=2、post[r]=1;in[i]=1、in[j]=3;post[l]=2、post[r]=1;in[i]=1、in[j]=3;post[l]=2、post[r]=1;in[i]=1、in[j]=3;
post[l]=5、post[r]=6;in[i]=5、in[j]=7;post[l]=5、post[r]=6;in[i]=5、in[j]=7;post[l]=5、post[r]=6;in[i]=5、in[j]=7;
由此每次都能找到根和左右区间,由于求层序遍历,而层序遍历满足:设本层递归以u号结点为根,那么其直接相连的子节点必然是u2、u2+1号结点,由此每次记录当前根的下标。此外,注意没说是满二叉树或完美二叉树,因此树可能存在很多空着的点,扫一下不是0的才算入序列。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int n,ceng[100010],post[100010],in[100010];
vector<int>v,vv;
void getceng(int l,int r,int i,int j,int u)
{
if(l>r||i>j) return;
int x=i;
ceng[u]=post[r];
while(x<=j&&in[x]!=post[r]) x++;
vv.push_back(post[r]);
getceng(l,l+x-i-1,i,x-1,u*2);
getceng(r-j+x,r-1,x+1,j,u*2+1);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>post[i];
for(int i=1;i<=n;i++) cin>>in[i];
getceng(1,n,1,n,1);
for(int i=1;i<=11000;i++)
if(ceng[i]!=0) v.push_back(ceng[i]);
for(int i=0;i<vv.size();i++)
{
cout<<vv[i];
if(i!=vv.size()-1) cout<<' ';
}
return 0;
}
拓展一下,如果给后序+中序求前序?也一样的。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int n,ceng[100010],post[100010],in[100010];
vector<int>v,vv;
void getceng(int l,int r,int i,int j,int u)
{
if(l>r||i>j) return;
int x=i;
ceng[u]=post[r];
while(x<=j&&in[x]!=post[r]) x++;
vv.push_back(post[r]);
getceng(l,l+x-i-1,i,x-1,u*2);
getceng(r-j+x,r-1,x+1,j,u*2+1);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>post[i];
for(int i=1;i<=n;i++) cin>>in[i];
getceng(1,n,1,n,1);
for(int i=1;i<=11000;i++)
if(ceng[i]!=0) v.push_back(ceng[i]);
for(int i=0;i<vv.size();i++)
{
cout<<vv[i];
if(i!=vv.size()-1) cout<<' ';
}
return 0;
}
该博客介绍了如何通过给定的二叉树后序和中序遍历序列,来构造并求解其层序遍历。博主详细解释了递归过程,指出在每个递归中,根节点可以将树分为两部分,并通过中序遍历的顺序确定左右子树。通过递归寻找根节点及其左右子树的后序遍历区间,最终得到层序遍历序列。代码示例展示了如何实现这一过程。
366

被折叠的 条评论
为什么被折叠?



