04-树6 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
结尾无空行
Code1 递归:
/*
如果二叉树的是一个完全二叉树,那么它的形态已经被确定了,然后又因为二叉搜索树的中序序列的性质,直接往已经确定形状的二叉树里面填数字就可以了,层序遍历以是下标1到n就可以了
*/
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 5;
int n, cnt;
int a[N], tree[N];
void inorder(int root)
{
if (root > n)
return;
inorder(root * 2);
tree[root] = a[cnt++];
inorder(root * 2 + 1);
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
sort(a, a + n);
inorder(1);
for (int i = 1; i <= n; i++)
cout << tree[i] << (i < n ? " " : "\n");
return 0;
}
Code2 递推:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>/*排序函数qsort需要的头文件*/
#define max 10000
int T[max], A[max];
int GetLeftLength(int n)
{
int s;
float c = 1; //记录数的层数
while (1)
{
s = (int)(pow(2, c)) - 1; //几层的所有所有树节点
c++;
if ((pow(2, c) - 1) > n) /*如果下一层的满二叉树超过了输入的数的节点就退出,
且把层数减1,因为下一层的左子树最大节点数就是上一层的总结点数*/
{
c--;
break;
}
}
int Left = 0;
if (n)
{
Left = (s - 1) / 2; //左边 满二叉树层数减 1 的节点数
int x = n - s; //下一层多出,但没有满的节点数
if (pow(2, c - 1) < x) // c-1 是因为每一层的总结点数是 2的 层数-1 次方
{
Left += (int)(pow(2, c - 1)); //下一层中左边最大的节点数是上一层的总结点数
}
else
{
Left += x;
}
}
return Left;
}
void solve(int ALeft, int ARight, int TRoot) /*从A段中选出正确的数字,填到T[]根节点数组中*/
{ /*初始调用为solve(0,N-1,0)*/
int n;
int L;
n = ARight + 1 - ALeft; /*计算树一共有多少个节点*/
if (n == 0)
return; //递归先考虑需要一个结束条件
L = GetLeftLength(n); /*计算出左子树的规模*/
int LeftTRoot, RightTRoot;
T[TRoot] = A[ALeft + L]; //根节点的下标是左子树的个数加1
LeftTRoot = TRoot * 2 + 1; /*数组从0开始的树,根与儿子的关系是 Root*2+1
数组从1开始的树,关系是 Root*2 */
RightTRoot = LeftTRoot + 1;
solve(ALeft, ALeft + L - 1, LeftTRoot);
/*ALeft + L - 1是指左子树的数组范围,刚才取到的根节点前一个值*/
solve(ALeft + L + 1, ARight, RightTRoot);
/*同理可得,ALeft + L + 1是指右子树的数组范围,刚才取到的根节点后一个值*/
}
int compare(const void *a, const void *b)
{
return *(int *)a - *(int *)b;
}
int main()
{
int N;
scanf("%d", &N);
int i;
for (i = 0; i < N; i++)
{
scanf("%d", &A[i]);
}
qsort(A, N, sizeof(int), compare);
/*qsort函数每个变量注释:(要排序的数组,数值个数,数值类型,比较函数要自己写)*/
solve(0, N - 1, 0); /*初始调用找第一个根节点为solve(0,N-1,0)*/
for (i = 0; i < N; i++)
{
if (i)
{
printf(" %d", T[i]);
}
else
{
printf("%d", T[i]);
}
}
return 0;
}