Problem Description
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
Solution
题意理解:给出一个序列,按层序遍历输出由该序列生成的完全二叉搜索树。
- 由于是完全二叉树,我们选择用数组来存。
- 先读入序列数组 A ,再对 A 非递减顺序排序,我们就可以在 A 数组上使用 Solve 函数递归生成完全二叉搜索树 T
- 直接顺序遍历 T 就是完全二叉搜索树的层序遍历
Solve 函数:
- 传入参数:A 中一个子树的左右端点、T 中待插入位置的根结点下标
- 首先计算子树规模,如果为空就返回。递归退出条件。
- 然后使用 GetLeftLength 获取左子树规模
- 根据左子树规模找到根结点填入 T
- 递归对左右子树进行 Solve
GetLeftLength 函数:
完全二叉树结点数与树高的关系:
- 传入参数:该树的规模 n
- 根据规模,对数函数向下取整后得到最大完美二叉树的树高 h
- 根据公式计算出左子树下面多出来的 x
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int n;
int A[1000], T[1000];
int cmp(const void*a, const void*b)
{
return *(int*)a - *(int*)b;
}
void GetInput()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf("%d", &A[i]);
qsort(A, n, sizeof(int), cmp);
}
int Min (int a, int b) { return a < b ? a : b; };
int GetLeftLength(int n)
{
int h, x;
h = (int)floor(log2(n + 1));
x = Min(n + 1 - (int)pow(2, h), (int)pow(2, h - 1));
return (int)pow(2, h - 1) - 1 + x;
}
void Solve(int Aleft, int Aright, int Troot)
{
int len, L;
len = Aright - Aleft + 1;
if (len == 0) return;
L = GetLeftLength(len);
T[Troot] = A[Aleft + L];
Solve(Aleft, Aleft + L - 1, Troot * 2 + 1);
Solve(Aleft + L + 1, Aright, (Troot + 1) * 2);
}
void Print()
{
for (int i = 0; i < n; i++)
if (i) printf(" %d", T[i]);
else printf("%d", T[i]);
}
int main()
{
GetInput();
Solve(0, n - 1, 0);
Print();
return 0;
}
Sum-up
-
本题需要掌握构造完全二叉树的方法,从数组里找根结点然后左右子树递归解决。
-
求左子树规模需要理解完全二叉树的树高与结点数的关系