数据结构初阶 堆的问题详解(三)

题目一

4.一棵完全二叉树的节点数位为531个,那么这棵树的高度为( )

A 11

B 10

C 8

D 12

我们有最大的节点如下

假设最大高度为10 那么它的最多节点应该是有1023

假设最大高度为9 那么它的最多节点应该是 511

所以说这一题选B

题目二

5.一个具有767个节点的完全二叉树,其叶子节点个数为()

A 383

B 384

C 385

D 386

还是一样 我们假设0度(叶节点)为X0 1度为X1 二度的为X2

根据前面得到的结论

X2 = X0 - 1

我们有

2X0 -1 + X1= 767

2X0 = 768 - X1

这个时候的X1为0

所以说叶节点的个数为384

该题选B

题目三 TOP K 问题

在N个数中找最大的前K个

解法一

排序 这个很简单了 就不多题 一个快排就搞定了

解法二

将N个数依次插入到大堆中 POPK次 就能取到最大的数

解法三

当我们需要寻找的数特别大的时候 比如说这个数是十个亿

十个亿就是四十亿个字节

大概就是4个G左右的内存

这样子的内存就直接否了解法一和解法二

我们创建一个K个数的小堆

比较堆的首元素的大小和要插入数字的大小

如果说插入的数字大于首元素 那么就替换首元素 之后向下调整

这样子到最后在这个堆里面留下的肯定是最大的K个数

大家仔细想想看是不是

(因为最大的数肯定会沉到最下面)

我们来简单实现一下这个算法的逻辑

我们首先先创建一个小堆

然后插入10000个数据

之后开始逐个比较堆顶元素和需要插入的元素的大小

如果说堆顶元素小于我们需要插入的元素

那么删除堆顶元素 之后插入我们的元素

大体思路就是这样子

我们用文件的方法来完成一下

1.建堆 -- 从a中前k个元素建小堆

1.1读出前k个数据建小堆

2.将剩余的n-k个元素依次与堆顶元素交换,不满足则替换

代码如下:

void PrintTopK(const char* file, int k)
{
	//1.建堆 -- 从a中前k个元素建小堆
	int* topk = (int*)malloc(sizeof(int) * k);
	assert(topk);

	FILE* fout = fopen(file, "r");
	if (fout == NULL)
	{
		perror("fopen error");
		return;
	}

	//读出前k个数据建小堆
	for (int i = 0; i < k; ++i)
	{
		fscanf(fout, "%d", &topk[i]);
	}
	for (int i = (k - 2) / 2; i >= 0; --i)
	{
		AdJustDown(topk, k, i);
	}
	//2.将剩余的n-k个元素依次与堆顶元素交换,不满足则替换
	int val = 0;
	//读出剩余的n-k个数据
	int ret = fscanf(fout, "%d", &val);
	while (ret != EOF)
	{
		if (val > topk[0])
		{
			topk[0] = val;
			AdJustDown(topk, k, 0);
		}
		ret = fscanf(fout, "%d", &val);
	}
	//打印出前k个元素
	for (int i = 0; i < k; i++)
	{
		printf("%d ", topk[i]);
	}
	printf("\n");
	free(topk);
	fclose(fout);
}

我们用示例来演示一下

造数据

代码如下

void CreateDate()
{
	//造数据
	int n = 10000;
	srand(time(0));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen fail");
		return;
	}
	for (int i = 0; i < n; i++)
	{
		int x = rand() % 10000;
		fprintf(fin, "%d\n", x);
	}
	fclose(fin);

}

现在实现的话要分成两步:

1.造数据

2.就用我们的PrintTopK函数

主函数这样写:

int main()
{
	CreateDate();
	//PrintTopK("data.txt", 10);
	return 0;
}
int main()
{
	//CreateDate();
	PrintTopK("data.txt", 10);
	return 0;
}

那我们怎么知道取出来的数据是最大的呢?

这时候我们可以看这步

int x = rand() % 10000;

我们可以设计10个大于10000的值,就可以知道程序是否正确

看下是否成小堆

是小堆

完美实现

以上便是本文所有内容,如有错误请各位大佬不吝赐教,感谢留言

相关推荐
Ljubim.te16 分钟前
软件设计师——数据结构
数据结构·笔记
Eric.Lee202123 分钟前
数据集-目标检测系列- 螃蟹 检测数据集 crab >> DataBall
python·深度学习·算法·目标检测·计算机视觉·数据集·螃蟹检测
林辞忧32 分钟前
算法修炼之路之滑动窗口
算法
￴ㅤ￴￴ㅤ9527超级帅43 分钟前
LeetCode hot100---二叉树专题(C++语言)
c++·算法·leetcode
liuyang-neu44 分钟前
力扣 简单 110.平衡二叉树
java·算法·leetcode·深度优先
penguin_bark1 小时前
LCR 068. 搜索插入位置
算法·leetcode·职场和发展
_GR1 小时前
每日OJ题_牛客_牛牛冲钻五_模拟_C++_Java
java·数据结构·c++·算法·动态规划
ROBIN__dyc1 小时前
表达式
算法
无限大.1 小时前
c语言实例
c语言·数据结构·算法
六点半8881 小时前
【C++】速通涉及 “vector” 的经典OJ编程题
开发语言·c++·算法·青少年编程·推荐算法