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 Ndistinct 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
题目要求根据输入的数据,建立一个完全二叉搜索树,然后输出层序遍历
由于是一次性输入的,所以可以利用完全二叉树和二叉搜索树的性质
首先完全二叉树的节点总数知道的话,那么左右子树的数量是可以确定下来的,因此可以先从小到大排序,然后再寻找树根(即左孩子的数量加1便是根)
找到根后左边的都比根小右边的都比根大符合搜索树的性质。
之后再递归以上过程就能建好树了
不过在这里我用的办法十分麻烦,还是用结构体数组的方式来存树的,导致建树和层序遍历都十分复杂。
完全二叉树完全可以用一个顺序数组来储存,因为左右子树的位置可以根据根的位置来确定。
层序遍历也直接输出数组即可。
#include <iostream>
#include <cmath>
#include <deque>
#define Tree int
using namespace std;
typedef struct _BSTree_node
{
int data;
Tree Left;
Tree Right;
}BSTree_node;
int partition(int a[], int left, int right); //快排,分隔函数
void quick_sort(int[], int left, int right); //快速排序
Tree find_BST_Root(BSTree_node[], int node_num, int low, int high);
void print_levelorder(BSTree_node[], Tree root);
int main()
{
int N;
cin >> N;
Tree *BTree = new Tree[N];
Tree Root;
BSTree_node *BSTree = new BSTree_node[N];
for (int i = 0; i < N; i++)
cin >> BTree[i];
quick_sort(BTree, 0, N - 1);
//for (int i = 0; i < N; i++)
// cout << BSTree[i]<<" ";
for (int i = 0; i < N; i++) {
BSTree[i].data = BTree[i];
BSTree[i].Left = BSTree[i].Right = -1;
}
Root = find_BST_Root(BSTree, N, 0, N - 1);
print_levelorder(BSTree, Root);
return 0;
}
Tree find_BST_Root(BSTree_node BSTree[], int node_num, int low, int high)
{
Tree root = low;
Tree root_pos = 0;
if (node_num == 0) return -1; //条件成立表明是空节点
if (low == high) return root; //条件成立表明只有一个节点
else if (low > high) exit(0); //出现这种情况且node_num又不是0,那么一般是出错了
//计算root位置
int hight = log(node_num) / log(2) + 1; //根据节点数计算出高度
int uplevel_num = pow(2, hight-1) - 1; //第hight - 1层节点数
int leaf_num = node_num - uplevel_num; //叶子节点数
if (leaf_num > pow(2,hight-1) / 2) //变成左边叶子节点数
leaf_num = pow(2, hight - 1) / 2;
root_pos = (uplevel_num - 1) / 2 + leaf_num;//root在数组中的位移量
root = low + root_pos;
//============
BSTree[root].Left = find_BST_Root(BSTree, root - low, low, root - 1);
BSTree[root].Right = find_BST_Root(BSTree, high - root, root + 1, high);
return root;
}
void print_levelorder(BSTree_node BSTree[], Tree root)//对于完全二叉树的数组,层序遍历直接把数组按顺序输出即可
{
bool flag = 1;//是否第一次输出,不是的就要在前面多加一个空格
deque<BSTree_node> squ;
BSTree_node node;
squ.push_back(BSTree[root]);
while (!squ.empty())
{
node = squ.front();
squ.pop_front();
if (node.Left != -1)
squ.push_back(BSTree[node.Left]);
if (node.Right != -1)
squ.push_back(BSTree[node.Right]);
if (flag)
{
cout << node.data;
flag = 0;
}
else
cout << " " << node.data;
}
}
//快排
void quick_sort(int a[], int left, int right)
{
int pivotpos;
pivotpos = partition(a, left, right);
if (left < right)
{
quick_sort(a, left, pivotpos - 1);
quick_sort(a, pivotpos + 1, right);
}
}
int partition(int a[], int left, int right)
{
int mid =a[left];
while (left < right)
{
while (mid <= a[right] && left < right) right--;
a[left] = a[right];
while (mid >= a[left] && left < right) left++;
a[right] = a[left];
}
a[left] = mid;
return left;
}