【数据结构】 堆排序与TopK问题详解

在学习完堆的创建后,就轮到了标题的两个问题
这两个问题在实际生活中会有比较强的实际问题解决能力
先分别解释一下

  • 堆排序:
    运用堆的思想进行排序,时间复杂度为O(NlogN)
  • TopK:
    从一大堆数据中选择K个最大或最小的数据,我们简称tTopK

堆的创建,关于堆的详情请点击。

目录

  • 堆排序:
    • 思想:
    • 代码实现:
    • 源代码:
  • TopK:
  • 思想:
    • 代码实现:
    • 源代码:

堆排序:

思想:

假设我们有一个小堆为N个数,先在要对其排序,那么这个小堆适合什么排序呢?

答案是降序

绝大部分同学可能都会认为是升序,
因为最上边的元素是最小的,我们将第一个固定住,在对其后边N-1个再次进行建堆,就可以完美得到一个升序的数组,
注意:

但是我们忽略了建堆的时间复杂度为O(lNogN),对N个数进行建堆,比冒泡排序有过之而无不及,所以我们不会去用这样一个华而不实的方法

所以我们小堆其实更适合降序,将建堆之后的第一个元素与数组末尾进行交换,再对这N-1个数进行向下调整算法,每调整一次时间复杂度为O(N),以此类推,再将第一个与倒数第二个交换…

代码实现:

我们既然进行排序,就要有一个待排序的数组,我们将数组传给堆排序,同样,当然也需要知道数组个数

	int arr[] = { 5,7,3,9,1,2,6,0 };
	HeapSort(arr, sizeof(arr) / sizeof(arr[0]));

然后我们就可以对这个数组进行建堆了,你的升降序也是根据你建的堆来进行的,要仔细区分
对于建堆,我们有两种方法

自上而下建堆:
这也是我们最容易想到的一种
利用循环将数组变成小堆

	for (int child = 0; child < size; child++)
	{
		AdjustUp(arr, child);
	}

自下而上建堆:
这是我们推荐的一种,因为他的时间复杂度小于上一种方式(从最后一个叶子节点的父节点开始,少了最后一层,而最后一层接近N/2个节点),同时,他只会用到向下调整算法,在进行排序时也只会用到向下算法,故很适合我们使用

	int parent = (size - 1 - 1) / 2;
	while (parent)
	{
		AdjustDown(arr, size, parent);
		parent--;
	}
	AdjustDown(arr, size, parent);

排序代码:

	//因为是小堆,排序降序
	int child = size - 1;
	for (int i = child; i > 0; i--)
	{
		Swap(&arr[0], &arr[i]);
		AdjustDown(arr, i, 0);
	}
	for (int i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}

源代码:

heap.cheap.h我们用到的依然是开头链接处的代码,这里我们直接引用他们

void HeapSort(int* arr, int size)
{
	//建堆:向下与向上
	
	向下
	//for (int child = 0; child < size; child++)
	//{
	//	AdjustUp(arr, child);
	//}
	
	//向上
	int parent = (size - 1 - 1) / 2;
	while (parent)
	{
		AdjustDown(arr, size, parent);
		parent--;
	}
	AdjustDown(arr, size, parent);
	
	//因为是小堆,排序降序
	int child = size - 1;
	for (int i = child; i > 0; i--)
	{
		Swap(&arr[0], &arr[i]);
		AdjustDown(arr, i, 0);
	}
	for (int i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}
}


int main()
{
	int arr[] = { 5,7,3,9,1,2,6,0 };
	HeapSort(arr, sizeof(arr) / sizeof(arr[0]));

	return 0;
}

TopK:

思想:

关于TopK我们有两种实现方法:

  1. N个数据进行建堆,在依次Pop掉堆顶,得到K个最大或最小的数据,但这种方式显然代价太大,且如果N太大,malloc会开辟不出来这么多数据的数组
  2. 我们先建一个K个数的堆,假设为小堆,那么此时还是问同学们一个问题,小堆适合选出最大的还是最小的呢?
    解:
    答案是最大的,
    因为我们在建好一个小堆后,需要拿堆顶的元素与N个数据中剩下的元素比较,又因为我们是小堆,所以当一个元素大于栈顶元素时,那个元素就会进入堆,我们进行向下排序,那个元素就会下沉,直到选出K个最大的数据,
    如果建立大堆的话,假设堆顶是K个数中最大的数据,就会挡在前边,另外几个次大的数据就会入不了堆,造成错误

代码实现:

首先创建一个文件,里面有很多的数据

void CreatData()
{
	FILE* fin = fopen("pata.txt", "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}

	//write data
	srand(time(NULL));
	for (int i = 0; i < 10000000; i++)
	{
		int x = (rand() + i) % 10000000;
		fprintf(fin, "%d\n", x);
	}

	fclose(fin);
}

注意:
创建完文件后我们要进入文件,改变几个数值(改变为超过取模的数字,这样我们就可以验证我们的代码准确性在这里插入图片描述
创建一个大小为K的堆

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

	// 建一个k个数小堆
	int* minheap = (int*)malloc(sizeof(int) * k);
	if (minheap == NULL)
	{
		perror("malloc error");
		return;
	}

将大数据中的前N个放入堆中

	// 读取前k个,建小堆
	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &minheap[i]);
		AdjustUp(minheap, i);
	}

依次读取,直到读取完毕并打印数据

	int x = 0;
	while (fscanf(fout, "%d", &x) != EOF)
	{
		if (x > minheap[0])
		{
			minheap[0] = x;
			AdjustDown(minheap, k, 0);
		}
	}

	for (int i = 0; i < k; i++)
	{
		printf("%d ", minheap[i]);
	}
	printf("\n");

	free(minheap);
	fclose(fout);

源代码:

void CreatData()
{
	FILE* fin = fopen("pata.txt", "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}

	//write data
	srand(time(NULL));
	for (int i = 0; i < 10000000; i++)
	{
		int x = (rand() + i) % 10000000;
		fprintf(fin, "%d\n", x);
	}

	fclose(fin);
}

void TopK(char* filename, int k)
{
	FILE* fout = fopen(filename, "r");
	if (fout == NULL)
	{
		perror("fopen fail");
		return;
	}

	// 建一个k个数小堆
	int* minheap = (int*)malloc(sizeof(int) * k);
	if (minheap == NULL)
	{
		perror("malloc error");
		return;
	}

	// 读取前k个,建小堆
	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &minheap[i]);
		AdjustUp(minheap, i);
	}

	int x = 0;
	while (fscanf(fout, "%d", &x) != EOF)
	{
		if (x > minheap[0])
		{
			minheap[0] = x;
			AdjustDown(minheap, k, 0);
		}
	}

	for (int i = 0; i < k; i++)
	{
		printf("%d ", minheap[i]);
	}
	printf("\n");

	free(minheap);
	fclose(fout);
}

int main()
{
//粘贴时注意先将创建数据的函数放出来,单独修改后再TopK
	//CreatData();
	TopK("data.txt", 5);
	return 0;
}

有问题及时询问博主,25小时高强度冲浪

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/209616.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何本地搭建个人hMailServer邮件服务并实现远程发送邮件

文章目录 前言1. 安装hMailServer2. 设置hMailServer3. 客户端安装添加账号4. 测试发送邮件5. 安装cpolar6. 创建公网地址7. 测试远程发送邮件8. 固定连接公网地址9. 测试固定远程地址发送邮件 前言 hMailServer 是一个邮件服务器,通过它我们可以搭建自己的邮件服务,通过cpola…

了解c语言中的结构体

介绍&#xff1a; 在C语言中&#xff0c;结构体是一种用户自定义的数据类型&#xff0c;它允许我们将不同类型的数据组合在一起&#xff0c;形成一个更为复杂的数据结构。结构体可以用来表示现实世界中的实体&#xff0c;如人员、学生、图书等。本篇博客将介绍结构体的基本概念…

Postgresql分区表

PostgreSQL 提供了三种分区表实现方式&#xff1a; range &#xff1a;范围分区list &#xff1a;列表分区hash &#xff1a;哈希分区 一、范围分区 根据某个字段的值&#xff0c;将数据存入不同的分区表中。 创建父表 create table test_person_table (name varchar(64),ag…

SpringSecurity工作原理

实现功能就是继承这几个对应功能的类。 大概工作流程 Spring Security 的过滤器&#xff08;Filters&#xff09;和拦截器&#xff08;Interceptors&#xff09;是 Spring Security 框架中用于保护 web 应用安全的重要组件。它们在处理 HTTP 请求时扮演不同的角色&#xff0c…

【动态规划】LeetCode-62.不同路径

&#x1f388;算法那些事专栏说明&#xff1a;这是一个记录刷题日常的专栏&#xff0c;每个文章标题前都会写明这道题使用的算法。专栏每日计划至少更新1道题目&#xff0c;在这立下Flag&#x1f6a9; &#x1f3e0;个人主页&#xff1a;Jammingpro &#x1f4d5;专栏链接&…

vue 中 mixin 和 mixins 区别

目录 前言 用法 全局Mixin 局部Mixin 代码 理解 高质量的Mixin使用 在Vue.js框架中&#xff0c;Mixin是一种非常重要和强大的功能&#xff0c;它允许开发者创建可复用的代码片段&#xff0c;并将其应用到一个或多个组件中。Vue提供了两种方式来使用Mixin&#xff0c;分别…

以太网PHY,MAC接口

本文主要介绍以太网的 MAC 和 PHY&#xff0c;以及之间的 MII&#xff08;Media Independent Interface &#xff0c;媒体独立接口&#xff09;和 MII 的各种衍生版本——GMII、SGMII、RMII、RGMII等。 简介 从硬件的角度看&#xff0c;以太网接口电路主要由MAC&#xff08;M…

OpenTelemetry系列 - 第4篇 OpenTelemetry K8S生态

目录 一、【Helm】添加OTel Helm repo二、【Helm Chart】OTel Collector2.1 daemonset2.2 deloyment 三、【K8S Operator】OTel Operator3.1 安装OTel Operator3.2 部署OpenTelemetryCollector3.2.1 Deloyment Mode3.2.2 DeamonSet Mode3.2.3 StatefulSetMode3.2.4 Sidecar Mod…

Matlab R2022b 安装成功小记

Matlab R2022b 安装成功小记 前言一、 下载链接二、 安装过程小记 叮嘟&#xff01;这里是小啊呜的学习课程资料整理。好记性不如烂笔头&#xff0c;今天也是努力进步的一天。一起加油进阶吧&#xff01; 前言 windows 10系统之前安装过Matlab R2010b做基础研究&#xff0c;最…

【高效开发工具系列】Hutool Http工具类

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

基于Spring Cloud智慧工地可视化管理平台源码

智慧工地是聚焦工程施工现场&#xff0c;紧紧围绕人、机、料、法、环等关键要素&#xff0c;综合运用物联网、云计算、大数据、移动计算和智能设备等软硬件信息技术&#xff0c;与施工生产过程相融合。 一、什么是智慧工地 智慧工地是指利用移动互联、物联网、智能算法、地理…

【Linux】awk 使用

awk 输出 // 打印所有列 $ awk {print $0} file // 打印第一列 $ awk {print $1} file // 打印第一和第三列 $ awk {print $1, $3} file // 打印第三列和第一列&#xff0c;注意先后顺序 $ cat file | awk {print $3, $1} …

DDPM代码详解

最近准备要学习一下AIGC&#xff0c;因此需要从一些基本网络开始了解&#xff0c;比如DDPM&#xff0c;本篇文章会从代码解析角度来供大家学习了解。DDPM(Denoising Diffusion Probabilistic Models) 是一种扩散模型。 扩散模型包含两个主要的过程&#xff1a;加噪过程和去噪过…

C语言--每日选择题--Day32

如果大家对读研究生和就业不知道如何抉择&#xff0c;我的建议是看大家的经济基础&#xff0c;如果家里不是很需要你们工作&#xff0c;就读研提升自己的学历&#xff0c;反之就就业&#xff1b;毕竟经济基础决定上层建筑&#xff1b; 第一题 1. 下面代码的结果是&#xff1a;…

牛客小白月赛82(A~C)

目录 A.谜题&#xff1a;质数 输入描述 输出描述 输入 输出 解析 B.Kevin逛超市 2 (简单版本) 输入描述 输出描述 输入 输出 思路 C.被遗忘的书籍 题目描述 输入描述 输出描述 输入 输出 输入 输出 思路 比赛链接 牛客小白月赛82_ACM/NOI/CSP/CCPC/ICPC算…

C#Backgroundworker与Thread的区别

前言 当谈到多线程编程时&#xff0c;C#中的BackgroundWorker和Thread是两个常见的选择。它们都可以用于实现并行处理和异步操作&#xff0c;但在某些方面有一些重要的区别。本文将详细解释BackgroundWorker和Thread之间的区别以及它们在不同场景中的使用。 目录 前言1. Backgr…

微软 Power Platform 零基础 Power Pages 网页搭建教程学习实践进阶以及常见问题解答(二)

微软 Power Platform 零基础 Power Pages 网页搭建教程学习实践进阶及常见问题解答&#xff08;二&#xff09; Power Pages 学习实践进阶 微软 Power Platform 零基础 Power Pages 网页搭建教程学习实践进阶及常见问题解答&#xff08;二&#xff09;Power Pages 核心工具和组…

基于单片机设计的智能水泵控制器

一、前言 在一些场景中&#xff0c;如水池、水箱等水体容器的管理中&#xff0c;保持水位的稳定是至关重要的。传统上&#xff0c;人们通常需要手动监测水位并进行水泵的启停控制&#xff0c;这种方式不仅效率低下&#xff0c;还可能导致水位过高或过低&#xff0c;从而对水体…

在 AlmaLinux9 上安装Oracle Database 23c

在 AlmaLinux9 上安装Oracle Database 23c 0. 下载 Oracle Database 23c 安装文件1. 安装 Oracle Database 23c3. 连接 Oracle Database 23c4. &#xff08;谨慎&#xff09;卸载 Oracle Database 23c 0. 下载 Oracle Database 23c 安装文件 版权问题&#xff0c;下载地址请等待…

企业加密软件有哪些(公司防泄密软件)

企业加密软件是专门为企业设计的软件&#xff0c;旨在保护企业的敏感数据和信息安全。这些软件通过使用加密技术来对数据进行加密&#xff0c;使得数据在传输和存储过程中不会被未经授权的人员获取和滥用。 企业加密软件的主要功能包括数据加密、文件加密、文件夹加密、移动设备…