数据结构暑期自学--MOOC浙江大学pta(7-7 Complete Binary Search Tree)

题目链接

前言:

看了很多题解,也知道这题有更简单的做法,但是还是根据陈老师的方法来实现一遍

关键点:

1、首先是明确用数组来存这颗完全二叉树,那是最省最适合的

2、关键思路:

是对这一堆数进行排序

然后求出左子树的结点的个数

进而可以求出根节点,进行赋值

之后有一个难点是如何根据根结点(该数组是以0下标开始)求出左子树和右子树的根结点:

int Left = Troot*2+1;
int Right = Left+1;

再不断递归

void solve(int ALeft, int ARight, int Troot)
{
	//ALeft为正在进行操作的数组的第一个数的下标, 同理ARight正在进行操作的数组的第一个数的下标
	//Troot为当前根结点所在的数组的位置
	//n为当前所求数组的个数 
	int n = ARight-ALeft+1;
	if (n==0)
	return;
	//L为左子树的结点个数 
	int L = GetLefttree(n);
	//求出根节点,进行赋值 
	T[Troot] = tree[L+ALeft];
	//推出左子树和右子树的根节点的个数 
	int Left = Troot*2+1;
	int Right = Left+1;
	//递归左右子树 
	solve(ALeft, ALeft+L-1, Left);
	solve(ALeft+L+1, ARight, Right);
}

3、如何求左子树的结点数:

首先明确(假如树的根节点为第一层, 即h = 1),则第n层有

pow(2, h-1);

 总共n层树,有

pow(2, h)-1;

看如下图

X的值是不能超过pow(2, h-1);

4、还有个细节是如何进行排序,c语言的排序函数是qsort,之前用的是c++都是sort,这是第一次,记录下用法

int compare(const void*a, const void*b)
{
    return *(int *)a - *(int*)b;
}

qsort(tree, n, sizeof(int), compare);

 tree为要排序数组的指针,可以用数组名

n为数组大小,即为要排序的大小

sizeof(int)为数组里的每一个元素的字节

compare为自定义的排序函数

代码:

# include <stdio.h>
# include <stdlib.h>
# include <math.h>
int n;
int tree[1010];
int T[1010];
int GetLefttree(int num)
{
	int a = num+1;
	a/=2;
	int sumh = 0;
	while (a)
	{
		sumh++;
		a/=2;
	}
	int x = num-pow(2, sumh)+1;
	if (x>pow(2, sumh-1))
	x = pow(2, sumh-1);
	return pow(2, sumh-1)+x-1;
}
void solve(int ALeft, int ARight, int Troot)
{
	int n = ARight-ALeft+1;
	if (n==0)
	return;
	int L = GetLefttree(n);
	T[Troot] = tree[L+ALeft];
	int Left = Troot*2+1;
	int Right = Left+1;
	solve(ALeft, ALeft+L-1, Left);
	solve(ALeft+L+1, ARight, Right);
}
int compare(const void*a, const void*b)
{
	return *(int *)a - *(int*)b;
}
int main()
{
	scanf("%d", &n);
	for (int i=0; i<n; i++)
	scanf("%d", &tree[i]);
	qsort(tree, n, sizeof(int), compare);
//	for (int i=0; i<n; i++)
//	printf("%d ", tree[i]);
	solve(0, n-1, 0);
	printf("%d", T[0]);
	for (int i=1; i<n; i++)
	printf(" %d", T[i]);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值