L2-3 完全二叉树的层序遍历 (25分)
一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是完美二叉树。对于深度为 D 的,有 N 个结点的二叉树,若其结点对应于相同深度完美二叉树的层序遍历的前 N 个结点,这样的树就是完全二叉树。
给定一棵完全二叉树的后序遍历,请你给出这棵树的层序遍历结果。
输入格式:
输入在第一行中给出正整数 N(≤30),即树中结点个数。第二行给出后序遍历序列,为 N 个不超过 100 的正整数。同一行中所有数字都以空格分隔。
输出格式:
在一行中输出该树的层序遍历序列。所有数字都以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
8
91 71 2 34 10 15 55 18
输出样例:
18 34 55 71 2 10 15 91
思路
对于递归和递推问题的求解一般有两部:第一步是分解子问题 ,第二部是确定问题的边界。
首先分解子问题:假设现在只有三个点:父节点,左孩子和右孩子,对于这颗简单树的后序遍历为:左孩子->右孩子->父亲节点 ,那么建树的时候只用把它的顺序反过来,即父亲节点->右孩子->左孩子
然后确定问题的边界:
根据完全二叉树的定义,每一层的结点都是优先从左往右放置,我们可以用一维数组模拟树,有几个点就需要占用几个数组结点:
1
2 3
4 5 6 7
8
然后递归建树 输出即可
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000;
int vis[maxn];
int a[maxn];
int tree[maxn];
int n,x;
void build(int i) //按与后序遍历相反的顺序建树
{
if(!vis[i]) //优先构建根节点
{
tree[i]=a[x--];
vis[i]=1;
}
if(!vis[i*2+1])build(i*2+1); //其次优先构建右儿子
if(!vis[i*2])build(i*2); //最后递归构建左孩子
}
int main()
{
cin>>n;
x=n;
for(int i=1;i<=maxn;i++)vis[i]=1; //所有数组vis设为1
for(int i=1;i<=n;i++)cin>>a[i],vis[i]=0; //接收后序遍历数组,vis为0的点才可以访问,跟n大小相同
build(1); //递归建树
int kongge=1; //控制空格输出
for(int i=1;i<=n;i++)
{
if(kongge==1)kongge=0;
else cout<<" ";
cout<<tree[i];
}
return 0;
}