分数 30
作者 陈越
单位 浙江大学
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:
The left subtree of a node contains only nodes with keys less than the node’s key.
The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
Both the left and right subtrees must also be binary search trees.
A Complete Binary Tree (CBT) is a tree that is completely filled, with the possible exception of the bottom level, which is filled from left to right.
Now given a sequence of distinct non-negative integer keys, a unique BST can be constructed if it is required that the tree must also be a CBT. You are supposed to output the level order traversal
Each input file contains one test case. For each case, the first line contains a positive integer N (≤1000). Then N distinct non-negative integer keys are given in the next line. All the numbers in a line are separated by a space and are no greater than 2000.
For each test case, print in one line the level order traversal sequence of the corresponding complete binary search tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.
10
1 2 3 4 5 6 7 8 9 0
6 3 8 1 5 7 9 0 2 4
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
C++ (g++)
根据二叉搜索树的性质,如果知道根结点左子树的结点个数,那么就知道根结点应该放置什么元素。而左子树结点的个数可以依靠完全二叉树的性质得到。(确定了结点个数,完全二叉树的结构就一定了)。
所以,先将输入的序列进行排序。然后输入序列一共有10个元素,那么完全二叉树的根结点的左子树一定含有6个结点(4层,3层为满的,共1+2+4=7个 左子树还剩3 个 3+1+2=6个结点),即根结点是从小到大排第七位的那个数字,也就是6,同时也可以确定后面的三个数字(7,8,9)一定是属于根节点的右子树的。
输入序列:1234567890
排好序:0123456789
可知,6是根结点,同理递归地填左子树和右子树(左子树和右子树也是完全二叉树)。先左子树部分,因为是完全二叉树,所以左子树的根结点的左边一定有3个结点,右边有两个结点,即是说0 1 2 3 4 5 6 7 8 9,3是左子树的根结点,依次类推。
填充数字时是先序遍历的应用。
假设调用核心算法之前,输入序列已经放到了数组A中,并对数组A做了一个从小到大的排列。
结果生成的树也存在一个数组里,叫做T。TRoot对应的是当前我们要考虑的这棵子树的根结点所在的位置。
solve函数要完成:从A中选出正确的数字,填到T[TRoot]中。
排序: qsort(A, N, sizeof(int), compare);
A 待排序序列的首元素地址
N 待排序序列的长度
sizeof(int) 要排序的元素的大小
compare 函数名称,可以叫做其他名称,功能是比较两个元素的大小
计算左子树的规模
H=log(N+1)
2^H-1+x=N
x要在x和pow(2,H-1)之间取最小
要计算左子树的规模。当有H层的时候,节点总数为2^H-1,那么计算左子树的规模的时候,因为也是完全二叉树,少了一层,节点个数就是2 ^(H-1)-1。
L=pow(2,H-1)-1+x
#include ;
using namespace std;
int *A;
int *T;
int min(int a,int b)
{
return a>b?b:a;
}
int GetLeftLength(int n)
{
int h=log2(n+1);
int x=n+1-pow(2,h);
x=min(x,pow(2,h-1));
int L=pow(2,h-1)-1+x;
return L;
}
void solve(int ALeft,int ARight,int TRoot)
{
//初始调用为(0,N-1,0)
int n=ARight-ALeft+1;//数组A中一段数字的个数
if(n==0) return;
int L=GetLeftLength(n);//计算出n个结点的树及其左子树有多少个结点
T[TRoot]=A[ALeft+L];
int LeftRoot=TRoot*2+1;//因为数组T中是从第0个位置开始存储的元素,所以根结点为TRoot,那么左孩子的下标就为TRoot*2+1
int RightRoot=LeftRoot+1;
solve(ALeft,ALeft+L-1,LeftRoot);
solve(ALeft+L+1,ARight,RightRoot);
}
int compare(const void *a,const void *b)
{
return *(int*)a-*(int*)b;
}
int main()
{
int N;
cin>>N;
A=(int *)malloc(sizeof(int)*N);
T=(int *)malloc(sizeof(int)*N);
for(int i=0;i<N;i++) cin>>A[i];
qsort(A,N,sizeof(int),compare);//将A数组排好顺序
solve(0,N-1,0);
for(int i=0;i<N-1;i++) cout<<T[i]<<" ";
cout<<T[N-1];
free(A);
free(T);
return 0;
}