L2-006 树的遍历 (25 分) 树经典问题 给定中序和(先序/后序)重建二叉树
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
输入格式:
输入第一行给出一个正整数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
思路
后序:左右根 左右根 根
中序:左根右 根 左根右
因此后序用来从后向前取得某个子树的根节点,而中序用来提供当前结点对于已建结点的左右孩子关系
层序遍历需要存储位置信息,不能纯用链式结构,需要数组来存每个结点,由于N=30,所以用数组下标作结点的位置的话极端情况(全在右子树)需要2^30的空间,必定栈溢出,所以使用类似于静态数组的方式,只是对结点加了一个表示位置的的成员,最后再对数组根据位置信息排序,即得到层次序列啦
更新:层序遍历可以只用链式结构,类似于广搜(我一时没想起来),所以很多做法都行,可以不用数组存储结点,是我太笨了QWQ
另一种比较好的(递归)解法:https://www.freesion.com/article/2513947642/
示意图:
ps:其实我觉得还是非递归比较好写
#include <bits/stdc++.h>
using namespace std;
struct node
{
int l,r,w,wei;
} a[50];
int hou[50];
map<int,int> zon;
int n,cnt,h=-1;
bool cmp(node a,node b)
{
return a.wei<b.wei;
}
int main()
{
cin>>n;
for(int i=0;i<n;++i)cin>>hou[i];
for(int i=0;i<n;++i)
{
int x;cin>>x;
zon[x]=i;
}
for(int i=n-1;i>=0;--i)
{
int x=hou[i];
if(h==-1)
{
h=cnt;
a[cnt].wei=1;
a[cnt++].w=x;
}
else
{
int p=h;
while(1)
{
if(zon[x]<zon[a[p].w])
{
if(a[p].l!=0)
p=a[p].l;
else
{
a[p].l=cnt;
a[cnt].wei=a[p].wei*2;
a[cnt++].w=x;
break;
}
}
else
{
if(a[p].r!=0)
p=a[p].r;
else
{
a[p].r=cnt;
a[cnt].wei=a[p].wei*2+1;
a[cnt++].w=x;
break;
}
}
}
}
}
sort(a,a+cnt,cmp);
for(int i=0;i<cnt;++i)
if(i!=cnt-1)cout<<a[i].w<<" ";
else cout<<a[i].w;
return 0;
}
数组模拟链式结构
#include <bits/stdc++.h>
using namespace std;
const int N=50;
int hou[N];
map<int,int> zon;
int n;
int w[N],l[N],r[N],cnt=1;
void bfs(){
queue<int> q;
q.push(1);
cout<<w[1];
while(!q.empty()){
int t=q.front();q.pop();
if(t!=1)
cout<<" "<<w[t];
if(l[t])q.push(l[t]);
if(r[t])q.push(r[t]);
}
}
int main()
{
cin>>n;
for(int i=0;i<n;++i)cin>>hou[i];
for(int i=0;i<n;++i){
int x;cin>>x;
zon[x]=i;
}
for(int i=n-1;i>=0;--i)
{
int x=hou[i];
int dx=zon[x];
if(cnt==1){
w[cnt]=x;
cnt++;
}else {
int t=1;
while(1){
int dy=zon[w[t]];
if(dx<dy){
if(l[t]==0){
l[t]=cnt;
w[cnt]=x;
cnt++;
break;
}
else t=l[t];
}else {
if(r[t]==0){
r[t]=cnt;
w[cnt]=x;
cnt++;
break;
}
else t=r[t];
}
}
}
}
bfs();
return 0;
}
然而实际上这题目只用下标索引左右节点就可以,因为数据并没有打算为难你。。。
#include <bits/stdc++.h>
using namespace std;
const int N=1000005;
int hou[50];
map<int,int> zon;
int n;
int w[N];
int main()
{
cin>>n;
for(int i=0;i<n;++i)cin>>hou[i];
for(int i=0;i<n;++i){
int x;cin>>x;
zon[x]=i;
}
memset(w,-1,sizeof w);
for(int i=n-1;i>=0;--i)
{
int x=hou[i];
int dx=zon[x];
if(w[0]==-1){
w[0]=x;
}else {
int t=0;
while(1){
int dy=zon[w[t]];
int l=t*2+1;
int r=t*2+2;
if(dx<dy){
if(w[l]==-1){
w[l]=x;
break;
}else t=l;
}else {
if(w[r]==-1){
w[r]=x;
break;
}else t=r;
}
}
}
}
for(int i=0;i<N;++i)
{
if(w[i]>-1){
n--;
if(n!=0)cout<<w[i]<<" ";
else cout<<w[i];
}
}
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析