二叉树-PTA-递归构造完全二叉搜索树

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

给定任意几个互不相同的数,一个完全二叉搜索树是可以被唯一确定的。本体就要求构造出这一树。
众所周知,完全二叉树可以用数组表示。

如下算法如果没看懂,可以自己把样例结果中的树画出来。会发现其实给定数的升序排列与目标树的中序遍历是一样的。所以此递归算法的核心也是“构造左,构造根,构造右”,因为在这样的顺序下,给定数可以按升序找到各自在目标树的位置,而这产生了该算法的灵魂(cnt及其++)。
事实上要理解这个cnt++,或者说

	BuildTree(2 * root_index, keys);		//构造左子树
	//注意,在左子树构造完成后,cnt已经递增为当前树的根的值在keys中的索引
	tree[root_index] = keys[cnt];			//构造根
	cnt++;
	//cnt++就是为了做好准备,把cnt递增至构造右子树所需要的位置
	BuildTree(2 * root_index + 1, keys);	//构造右子树

这一部分内容,可以用中序遍历序列的自相似性来考虑,会好很多。事实上,前序中序后序遍历都具有这种自相似性。这一点在很多问题里都是极端重要的!

My answer:

#include <stdio.h>
#include <stdlib.h>

#define MAXN 1000
int tree[MAXN];
int N;
int cnt = 0;	
//这个cnt的构建和++是这一递归算法的灵魂
void SortArray(int* keys);
void BuildTree(int root_index, int* keys);
void Print(int* keys);
int main(void)
{
	int i;
	scanf("%d", &N);

	int* keys = (int*)malloc(N * sizeof(int));
	for (i = 0; i <= N - 1; i++) {
		scanf("%d", &keys[i]);
	}

	SortArray(keys);
	
	BuildTree(1, keys); //Core algorithm
	//最左下角的最小左子树的根的值在keys中的索引是1
	Print(keys);
	return 0;
}

void BuildTree(int root_index, int* keys)	
//传入当前树根的位置,这一函数可以在tree中构造这个树
{
	if (root_index > N)return;

	BuildTree(2 * root_index, keys);		//构造左子树
	//注意,在左子树构造完成后,cnt已经递增为当前树的根的值在keys中的索引
	tree[root_index] = keys[cnt];			//构造根
	cnt++;
	//cnt++就是为了做好准备,把cnt递增至构造右子树所需要的位置
	BuildTree(2 * root_index + 1, keys);	//构造右子树

	return;
}
void SortArray(int* keys) //插入排序
{
	int cur_val, pre_index;
	for (i = 1; i <= N - 1; i++) {
		cur_val = keys[i]; pre_index = i - 1;
		while (pre_index >= 0 && keys[pre_index] > cur_val) {
			keys[pre_index + 1] = keys[pre_index];
			pre_index--;
		}
		keys[pre_index + 1] = cur_val;
	}
	return;
}
void Print(int* keys)
{
	int i;
	for (i = 1; i <= N; i++) {
		if (i == N)printf("%d", tree[i]);
		else printf("%d ", tree[i]);
	}
	return;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值