1064 Complete Binary Search Tree (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 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
题目大意:
二叉搜索树(BST)是具有以下定义的一种二叉树:
- 其左子树的所有节点(若存在)的关键字都比根节点的小;
- 其右子树的所有节点(若存在)的关键字都不比根节点的小;
- 其左/右子树自身也是一颗二叉搜索树(BST)。
完全二叉树(CBT):
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
现在给定N个关键字,按层序遍历打印由这些关键字的树节点组成的特定二叉树,这个二叉树既是二叉搜索树又是完全二叉树,也就是完全二叉搜索树。
输入:第一行N:多少个节点(关键字)
第二行N个非负整数:关键字序列
算法思路:
- 输出是按层序遍历的,那么此二叉树用数组存储法最佳,因为二叉树的数组顺序就是层序遍历的顺序;
- 数组从下标1开始,则以下标i表示的每个节点,其左孩子节点是下标(2*i)、右左孩子节点是下标(2*i+1)。
- 如何构造此二叉树呢?注意二叉搜索树的中序遍历就是此树关键字的非降序排序。先将输入的N个数按非降序排列,即可得到此树中序遍历时的输出序列,那只要当做此树已经构造好了,按中序遍历此树,将访问根节点的操作替换为赋值根节点即可构造此树。
- 最后按存储二叉树的数组顺序遍历即为层序遍历。
C++代码如下:
#include<cstdio>
#include<algorithm>
using namespace std;
const size_t MAX_N = 1001;
int NUM; //树节点个数
int A[MAX_N]; //BST中序遍历时的序列
int BT[MAX_N]; //二叉树的数组表达,其中BT[0]禁用!
size_t ib = 0; //用于中序遍历BST树,即BST[]按序遍历
void inorder(size_t i) {
if (i > NUM)return; //数组树越界——>子节点不存在
inorder(2 * i); //访问左子树
BT[i] = A[ib++]; //根节点(按BST中序遍历顺序写入)
inorder(2 * i + 1); //访问右子树
}
int main() {
scanf("%d\n", &NUM);
for (size_t i = 0; i < NUM; i++) {
scanf("%d", &A[i]);
}
sort(A, A + NUM); //非降序排序等同BST的中序遍历输出顺序
inorder(1); //从根节点开始按中序遍历赋值
printf("%d", BT[1]); //堆存储二叉树的顺序就是层序遍历的顺序,直接按序输出即可。
for (size_t i = 2; i <= NUM; i++) {
printf(" %d", BT[i]);
}puts("");
system("pause");
return 0;
}
Python3 代码如下:
num = int(input())
A = sorted([int(a) for a in input().split(' ')])
BT = [0 for i in range(num + 1)]
def inOrder( i: int):
global num,A,BT
if i <= num:
inOrder(2 * i)
BT[i] = A[0];
A = A[1:]
inOrder(2 * i + 1)
inOrder(1)
print(' '.join(map(str,BT[1:])))
C语言代码如下:
由于C语言qsort要写比较函数,注意题目中“All the numbers in a line are separated by a space and are no greater than 2000.”,所有元素是[0,2000]的整数,可以用一维桶排序解决非递减遍历BST的问题。
#include<stdio.h>
#include<stdlib.h>
#define FOR(I,S,E) for(int I=(S);I<(E);I++)
#define MAX_N 1001
int BT[MAX_N]; //二叉树的数组表达,其中BT[0]禁用!
#define MAX 2000 //non-negative integer,no greater than 2000
int Count[MAX + 1] = { 0 }; //桶排序,数值范围限定在0~2000
void push(int a) {++Count[a];}
int pop() { //从Count中取出最小元素并移除
static int a = 0; //BST遍历的关键字,对应Count的下标
while (a <= MAX && Count[a] <= 0)++a;
--Count[a];
return a;
}
size_t NUM; //二叉树节点数
void inorder(size_t i) {
if (i > NUM)return; //数组树越界——>子节点不存在
inorder(2 * i); //访问左子树
BT[i] = pop(); //根节点(按BST中序遍历顺序写入)
inorder(2 * i + 1); //访问右子树
}
int main() {
scanf("%d\n", &NUM);
FOR(i, 0, NUM) {
int a; scanf("%d", &a);
push(a);
} // Count[a]=m 表示输入的N个数中有m个元素a。
inorder(1); //从根节点开始按中序遍历赋值
printf("%d", BT[1]); //堆存储二叉树的顺序就是层序遍历的顺序,直接按序输出即可。
for (size_t i = 2; i <= NUM; i++) {
printf(" %d", BT[i]);
}puts("");
system("pause");
return 0;
}