PAT_A1064
PAT甲级1064.
目录
A1064
题目
样例
输入:
10
1 2 3 4 5 6 7 8 9 0
输出:
6 3 8 1 5 7 9 0 2 4
思路和坑点
二叉搜索树的中序遍历是有序的,因此排序后,根据次该性质进行计算。完全二叉树的结构可以通过结点数来确定,可以计算出左右子树的结点个数,从而确定树的根结点在中序中的位置,然后递归解决左子树和右子树的根,由于层次序列的整体顺序为root,2*root+1(左子树的根),2*root+2(右子树的根)
,因此可以在递归中直接得出层次序列的结点顺序。
AC代码
#include<bits/stdc++.h>
using namespace std;
vector<int> L,v; //用于存放数据,L为最终的层次输出序列,v为输入序列
int getroot(int l,int r){ //计算输入序列中下标l~r中字数的根,并返回其下标
int num=r+1-l,layer=0; //num为l~n中的元素个数,layer为该区间元素构成完全二叉树的层数
while((int)pow(1.0*2,layer)-1<=num) //计算layer表示为最大整层数+1
layer++;
layer--; //循环结束,把layer取到最大整层数
int flnum=num-((int)pow(1.0*2,layer)-1); //flnum为最后一层的结点个数
int tag=pow(1.0*2,layer-1),leftnum; //tag为满二叉时,最后一层结点数的一半,leftnum为l~n区间构成的树的左子树元素个数
if(flnum<=tag) leftnum=tag-1+flnum; //如果最后一层不满一半,计算左子树元素个数
else leftnum=2*tag-1; //如果满一半,计算左子树个数
return leftnum+l; //返回根结点所在的下标
}
void solve(int l,int r,int root){ //将l~n区间中的根结点放置在层次序列的对应位置上
if(l>r) return; //如果该区间没有元素,直接返回
int index=getroot(l,r); //计算根在输入序列中的位置
L[root]=v[index]; //将根放在层次序列的位置上
solve(l,index-1,2*root+1); //递归求解右子树的根
solve(index+1,r,2*root+2); //递归求解右子树的根
}
int main(void){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt","r",stdin);
#endif
int n;
scanf("%d",&n);
v.resize(n); L.resize(n);
for(int i=0;i<n;i++)
scanf("%d",&v[i]);
sort(v.begin(),v.end()); //排序,搜索树的中序序列是有序的
solve(0,n-1,0); //递归的起始参数
for(int i=0;i<n;i++){ //输出结果
if(i) putchar(' ');
printf("%d",L[i]);
}
return 0;
}