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
给定任意几个互不相同的数,一个完全二叉搜索树是可以被唯一确定的。本体就要求构造出这一树。
众所周知,完全二叉树可以用数组表示。
如下算法如果没看懂,可以自己把样例结果中的树画出来。会发现其实给定数的升序排列与目标树的中序遍历是一样的。所以此递归算法的核心也是“构造左,构造根,构造右”,因为在这样的顺序下,给定数可以按升序找到各自在目标树的位置,而这产生了该算法的灵魂(cnt及其++)。
事实上要理解这个cnt++,或者说
BuildTree(2 * root_index, keys); //构造左子树
//注意,在左子树构造完成后,cnt已经递增为当前树的根的值在keys中的索引
tree[root_index] = keys[cnt]; //构造根
cnt++;
//cnt++就是为了做好准备,把cnt递增至构造右子树所需要的位置
BuildTree(2 * root_index + 1, keys); //构造右子树
这一部分内容,可以用中序遍历序列的自相似性来考虑,会好很多。事实上,前序中序后序遍历都具有这种自相似性。这一点在很多问题里都是极端重要的!
My answer:
#include <stdio.h>
#include <stdlib.h>
#define MAXN 1000
int tree[MAXN];
int N;
int cnt = 0;
//这个cnt的构建和++是这一递归算法的灵魂
void SortArray(int* keys);
void BuildTree(int root_index, int* keys);
void Print(int* keys);
int main(void)
{
int i;
scanf("%d", &N);
int* keys = (int*)malloc(N * sizeof(int));
for (i = 0; i <= N - 1; i++) {
scanf("%d", &keys[i]);
}
SortArray(keys);
BuildTree(1, keys); //Core algorithm
//最左下角的最小左子树的根的值在keys中的索引是1
Print(keys);
return 0;
}
void BuildTree(int root_index, int* keys)
//传入当前树根的位置,这一函数可以在tree中构造这个树
{
if (root_index > N)return;
BuildTree(2 * root_index, keys); //构造左子树
//注意,在左子树构造完成后,cnt已经递增为当前树的根的值在keys中的索引
tree[root_index] = keys[cnt]; //构造根
cnt++;
//cnt++就是为了做好准备,把cnt递增至构造右子树所需要的位置
BuildTree(2 * root_index + 1, keys); //构造右子树
return;
}
void SortArray(int* keys) //插入排序
{
int cur_val, pre_index;
for (i = 1; i <= N - 1; i++) {
cur_val = keys[i]; pre_index = i - 1;
while (pre_index >= 0 && keys[pre_index] > cur_val) {
keys[pre_index + 1] = keys[pre_index];
pre_index--;
}
keys[pre_index + 1] = cur_val;
}
return;
}
void Print(int* keys)
{
int i;
for (i = 1; i <= N; i++) {
if (i == N)printf("%d", tree[i]);
else printf("%d ", tree[i]);
}
return;
}