# 菜鸡奋斗路04-树6 Complete Binary Search Tree

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  (). Then  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


首先，菜鸡就考虑用链表or数组来表示树，在这道题里，完全二叉树，意味着即使是数组存储，也不会存在空间的浪费。并且，数组存储的顺序就是层序遍历的输出顺序，这么看来，如果使用数组，只需要解决建树问题，层序遍历可以直接输出。

其次，如何实现建立完全二叉搜索树，乍一看有两种想法：

1.实时模拟结点插入过程。菜鸡已经知道如何建立平衡二叉搜索树，其窍门是在每次插入结点的时候实时判断父结点是否平衡，从而调控树。那么在这里，也应该可以在每次插入结点的时候改进判断条件，调整树，得到正确的完全二叉搜索树。

（然而，很惨烈的是，这里的判断条件菜鸡没能想出来，在平衡二叉搜索树时，只需要检验某结点的左右子树高度，就能判断是否平衡；完全二叉搜索树时，某结点左右子树的结点数之间没有很明确的关系。）

2.调整已有完全二叉树。所谓完全二叉树，一旦确定总结点数，其形状结构是完全确定的。也就是说，我们可以根据传入的总结点数，默认已经建立起一颗完全二叉树，其从上到下从左到右的结点即为输入数列。我们需要做的，就是把这棵树，一个结点一个结点的调整成搜索树（或一个结点一个结点提取出来，放入另一空树内）。

先把输入序列递增排序，这样才能确保上述方法可行。

设树高h层，那么前H=h-1层一定都是满的，而最后第h层情况特殊。所以，先确定左子树在前H层的结点数目，而第h层中左子树所占的结点数=Min{ （树总结点数 - H层满树结点数）；第h层满结点/2}。

——————我是分割线啦啦啦————————————

#include<stdio.h>
#include<stdlib.h>
#include<cmath>
#include<math.h>
#define Maxsize 1000

int GetLeftLength(int n)
{
int h,X,L;
h=floor(log(n+1)/log(2));         //floor(i)返回一个小于i的最大整数，用于取得树高h
X=n-pow(2,h)+1;                  //最底层结点数X(可能值)
if(pow(2,h-1)>X)
L=pow(2,h-1)-1+X;
else
L=pow(2,h-1)-1+pow(2,h-1);
return L;
}

void solve(int ALeft,int ARight,int TRoot,int T[],int A[])
{
int n,L,LeftTRoot,RightTRoot;     //n为当前处理段的总结点数，L为当前结点左子树结点数
n=ARight-ALeft+1;                 //LeftTRoot左儿子，RightTRoot右儿子
if(n==0) return;                 //退出递归的条件：已到叶结点
L=GetLeftLength(n);
T[TRoot]=A[ALeft+L];              //确定当前根位置结点数值
LeftTRoot=TRoot*2+1;
RightTRoot=LeftTRoot+1;
solve(ALeft,ALeft+L-1,LeftTRoot,T,A);   //递归得解决左子树
solve(ALeft+L+1,ARight,RightTRoot,T,A);  //递归得解决右子树

}

void setorder(int A[],int N)     //orz，直接用了O（N2）简单排序，顾不得那么多了...
{
for(int i=0;i<N;i++)
{
for(int j=0;j<N-i-1;j++)
{
if(A[j]>A[j+1])
{
int c=A[j+1];
A[j+1]=A[j];
A[j]=c;
}
}
}
}

int main()
{
int A[Maxsize],T[Maxsize];//A为输入完全二叉树，T为空树，需将A中结点按要求填入T中。
int num;
scanf("%d",&num);
getchar();
for(int i=0;i<num;i++)
scanf("%d",&A[i]);
setorder(A,num);     //将输入序列递增排序
solve(0,num-1,0,T,A); //根据要求建立完全二叉搜索树
printf("%d",T[0]);
for(int j=1;j<num;j++)
{
printf(" %d",T[j]);
}
return 0;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120