MOOC数据结构课程 题集11 Complete Binary Search Tree

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值