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 sequence of this BST.
Input Specification:
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.
Output Specification:
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.
Sample Input:
10 1 2 3 4 5 6 7 8 9 0
Sample Output:
6 3 8 1 5 7 9 0 2 4
小结:
这道题给我启发挺大的,递归还能这么用?!好像慢慢要理解递归的威力啦。
之前自己思考时,已经想到了先满足完全二叉树,再调整为二叉搜索树,但是在怎么求根结点那里卡住了,还是缺乏编程思维,没有了解递归的真谛;收获颇多,诸君共勉。
/*
给定一组序列,给出它的完全二叉搜索树,1.这棵树是完全二叉树 2.是二叉搜索树 3.所有子树都是完全二叉搜索树
思路:找树根->递归找左树根->递归找右树根
核心算法:如何找树根:先排序->根据给定的数据个数N,推算出这棵树的高度H(高度为H的完全二叉树 最大结点数是2^H-1)
所以N<=2^H-1 ①H=1,while(pow(2,H)<=N){H++;} 可以算出H,进而可以求出左边的结点个数L
②H>=log2(N+1) 可以求得完美二叉树的高度 如果 2^H-1==N H就是这棵树的高度 否则就是H+1
math.h里有log函数 是指以自然数e为底 根据换底公式 可以得出以2为底 log(N+1)/log(2)
*/
#include <stdio.h>
#include <math.h>
#define index int
void FromSmallToLargeSort( int* SortArray,int N );//给数组排序
void Swap( int* a,int *b ); //排序时用到的交换数组中两个值
void Solve( int* SortArray,index SortArrayLeft,index SortArrayRight,int* CBST,index Root );//核心算法
/* 排好序的数组 数组的左边下标 右边下标 树 树根*/
int GetLeftNumbers( int n ); //计算左子树的结点个数
int Min( int X,int Y);
int main()
{
int N;
scanf("%d",&N);
int i,SortArray[N];
for(i=0;i<N;i++){
scanf("%d",&SortArray[i]);
}
FromSmallToLargeSort( SortArray,N );
int CBST[N+1];
Solve( SortArray,0,N-1,CBST,1);
int first = 1;
for(i=1;i<N+1;i++){
if(first){
printf("%d",CBST[i]);
first = 0;
}else{
printf(" %d",CBST[i]);
}
}
return 0;
}
void FromSmallToLargeSort( int* SortArray,int N )
{
int i,j;
for(i=1;i<N;i++){
for(j=0;j<i;j++){
if(SortArray[j] > SortArray[i]){
Swap( &SortArray[j],&SortArray[i]);
}
}
}
}
void Swap( int* a,int *b )
{
int Temp = *a;
*a = *b;
*b = Temp;
}
void Solve( int* SortArray,index SortArrayLeft,index SortArrayRight,int* CBST,index Root )
{ /*根据一组有序的数组SortArray,推算出对应完全二叉搜索树的树根*/
//首次调用 时取数组的最左和最右 即0 和 N-1,树根下标是 1
int n = SortArrayRight - SortArrayLeft +1;//数组个数
if(n==0){
return;//递归出口
}else{
int L,LeftRoot,RightRoot;
L = GetLeftNumbers( n ); //左子树的结点个数
CBST[Root] = SortArray[SortArrayLeft+L]; //根据左子树的结点个数 推算出根结点
LeftRoot = Root*2; //左子树
RightRoot = LeftRoot+1; //右子树
Solve( SortArray,SortArrayLeft,SortArrayLeft+L-1,CBST,LeftRoot ); //递归求左子树的根结点
Solve( SortArray,SortArrayLeft+L+1,SortArrayRight,CBST,RightRoot );//递归求右子树的根结点
}
}
int GetLeftNumbers( int n )
{
int K = (int)(log(n+1)/log(2));//完美二叉树的层数
/*
K =0;
while(pow(2,K)-1<n){
K++;
} 这样求出的是总层数
*/
int X = n+1-(int)pow(2,K); //根据完美二叉树的层数 求出 最下面一层非完美的结点个数
int XL = Min( X,(int)pow(2,K-1)); //根左树最下一层结点个数 最多等于上一层结点个数;比上一层少 非完美结点全在左边,
int nL = (int)pow(2,K-1) - 1 + XL; //根结点左边结点个数
return nL;
}
/* 推导思路:N个结点的完全二叉树,最下一层非完美结点数为X =0表示这是棵完美二叉树
到第K层都是完美二叉树,总结点数为2^k-1
则N = 2^K-1+X;
根左树也是完全二叉树(或完美二叉树) 有K-1完美层 2^(K-1)-1
结点总数NL=2^(K-1)-1 + XL */
int Min( int X,int Y)
{
return (X<Y?X:Y);
}