堆排序经典问题【TopK】

news2025/1/17 21:46:12

前言

在上文我们讲了堆排序的实现(点此调整),我们先简单回顾一下。
在进行堆排序之前,需要建一个堆,由于排序是将堆顶数据与堆底交换,所以排升序建大堆,降序建小堆。
堆排序的代码

//向下调整算法
void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child+1 < n && a[child] < a[child + 1])
		{
			child++;
		}
		if (a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

//向下调整创建堆
void CreateHeap(int* a, int n)
{
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(a, n, i);
	}
}

//堆排序
void HeapSort(int* a, int n)
{
	CreateHeap(a, n);
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		
		AdjustDown(a, end, 0);
		--end;
	}
	
}
void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}

int main()
{
	int a[] = { 5,6,8,2,3,7,10,4,9,1 };
	
	printf("排序前:");
	PrintArray(a, sizeof(a) / sizeof(int));
	
	//CreateHeap(a, sizeof(a) / sizeof(int));
	HeapSort(a,sizeof(a) / sizeof(int));
	
	printf("排序后:");
	PrintArray(a, sizeof(a) / sizeof(int));
	
	return 0;
}

TopK问题

假设给你10亿个整数(大小约为3.73G),让你找出最大\最小的前k个数。

情况一(无内存限制)

在不管内存的情况下我们可以直接建造一个能存放4亿的整数的堆,再继续堆排序,取出前k个数据。

情况二(内存只有1GB)

那么这时候给你一个限制,如果这个内存只有1G该怎么办。(四亿个整型的数据存放再硬盘)
这很简单,我们可以分四次从硬盘中读取,然后每次取出最大/最小的前k个数,最后再从这4个前k个数中求最大/最小的前k个数。

情况三(内存只有1KB)

我们同样可以使用情况二的方法,只剩读取的次数变多的,但是但是,这样的效率就太慢了。
这时候就有一个很优的方法:我先建K个数的小堆,让我从硬盘中读取的数据与堆顶数据比较,如果大于,就将堆顶数据替换成读取的数据,然后再向下调整。
由于我建的是小堆,就绝对能确定堆顶数据是堆中最小的数据,如果我的堆顶数据就是第K大的数据,就代表我这个堆里的数据就前K大的数据。
当我要找前k小的时候,将建造K个数的大堆就可以了,其他操作都大致相同,只需要修改大小于号就可以了。

//向下调整算法
void AdjustDown(HPDataType* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child+1 < n && a[child] < a[child + 1])
		{
			child++;
		}
		if (a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

//打印数组
void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}

void CreateNDate()
{
	// 造数据
	int n = 10000;
	srand(time(0));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}

	for (size_t i = 0; i < n; ++i)
	{
		int x = rand() % 1000000;
		fprintf(fin, "%d\n", x);
	}

	fclose(fin);
}

void PrintTopK(int k)
{
	const char* file = "data.txt";
	FILE* fout = fopen(file, "r");
	if (fout == NULL)
	{
		perror("fopen error");
		return;
	}

	int* KMinHeap = (int*)malloc(k * sizeof(int));
	if (KMinHeap == NULL)
	{
		perror("malloc fail");
		exit(1);
	}

	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &KMinHeap[i]);
	}

	for (int i = (k - 2) / 2; i > 0; i--)
	{
		AdjustDown(KMinHeap, k, i);
	}
	int val = 0;
	while (fscanf(fout, "%d", &val) != EOF)
	{
		if (val > KMinHeap[0])
		{
			KMinHeap[0] = val;
			AdjustDown(KMinHeap, k, 0);
		}
	}
	printf("前%d大的数:", k);
	PrintArray(KMinHeap, k);
	fclose(fout);
}

int main()
{
	//CreateNDate();
	PrintTopK(10);
	return 0;
}

在这里插入图片描述
注:
这前十个数都是自己造的数,这些数是一定大于其他数的,我们可以用这些自己造的数来确认是否成功。
这里的TopK并没有要求需要排序,只是要求找出前K个最大(最小)数,如果你要排序,就调用堆排序的函数就可以了。

结语

最后感谢您能阅读完此片文章,如果有任何建议或纠正欢迎在评论区留言,也可以前往我的主页看更多好文哦(点击此处跳转到主页)。
如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Nginx+Tomcat负载均衡、动静分离群集方案

一、Tomcat简介 在现代 Web 服务架构中&#xff0c;Tomcat 和 Nginx 是两个至关重要的组件&#xff0c;负责处理用户请求并实现高性能的服务。本篇博客将深入探讨这些技术的原理和部署配置方法。 最初是由Sun的软件构架师詹姆斯邓肯戴维森开发。安装Tomcat后&#xff0c;安装…

一文细谈SNN的基本数学原理,LIF模型,STDP与STBP学习方法

首先本文是读完 如何看待第三代神经网络SNN&#xff1f;详解脉冲神经网络的架构原理、数据集和训练方法 原创-CSDN博客 一文通俗入门脉冲神经网络(SNN)第三代神经网络-CSDN博客 两篇文章的总结&#xff0c;文章仅用于学习。 本文主要讨论STDP和STBP方法。 我们都知道&…

Zynq学习笔记--AXI4-Stream到视频输出IP是如何工作的?

目录 1. 简介 2. 原理详解 2.1 示例工程 2.2 AXI4-Stream to Video Out 3. Master/Slave Timing Mode 3.1 Slave Timing Mode 3.2 Master Timing Mode 4. 总结 1. 简介 本文主要介绍了 AXI4-Stream 到视频输出 的内容。其中&#xff0c;示例工程展示了一个具体的设计&…

CSS id选择器

目录 任务描述 相关知识 id选择器 id选择器语法 类选择器与id选择器的区别 编程要求 任务描述 在本关中&#xff0c;你将通过id选择器的方式完成页面菜单栏样式布局&#xff0c;栏目导航等任务。 完成任务之后&#xff0c;基本页面效果如下&#xff1a; 动态效果如下&am…

瑞昱半导体AMB82 MINI SD卡加载模型RTSP视频流AI识别图像和声音分类

AMB82 MINI Arduino的方法迭代更新十分及时&#xff0c;github维护也十分频繁。最新推出的4.0.7版本开始支持SD卡加载模型。有的网友装了4.0.6版本是看不到摄像头和模型加载选项的。 用这个实例来呈现RTSP视频流AI识别图像&#xff0c;同时展示对声音进行分类效果。 SDK升级到…

XUbuntu24.04之制作ISO镜像启动盘(二百四十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

【数据结构与算法 经典例题】括号匹配问题

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法 经典例题》C语言 期待您的关注 ​​ 目录 一、问题描述 二、解题思路 &#x1f343;破解之道 &#x1f343;…

基于大模型的360度全景图像生成技术:L-MAGIC

在数字技术的浪潮中,我们迎来了一项革命性的创新——L-MAGIC,一个能够基于一张普通照片和简单文字描述,快速生成360度全方位全景画面的系统。L-MAGIC不仅提供了沉浸式的视觉体验,还融合了多种素材和技术手段,让全景图像的生成变得更加丰富和真实。 技术亮点 1. 多角度视…

小熊家务帮day19-day21 订单模块2(取消订单,退款功能等)

目录 1 订单退款功能1.1 需求分析1.2 接口分析1.3 退款流程分析1.4 表结构设计1.5 取消未支付订单实现1.5.1 接口开发Controller层开发Service层开发 1.5.2 接口测试 1.5 取消已支付订单实现 1 订单退款功能 1.1 需求分析 用户下单成功可以取消订单&#xff0c;在订单的不同状…

【网络编程开发】11.IO模型 12.IO多路复用

11.IO模型 什么是IO: IO 是 Input/Output 的缩写&#xff0c;指的是输入和输出。在计算机当中&#xff0c;IO 操作通常指将数据从一个设备或文件中读取到计算机内存中&#xff0c;或将内存中的数据写入设备或文件中。这些设备可以包括硬盘驱动器、网卡、键盘、屏幕等。 通常用…

kettle_Hbase

kettle_Hbase ☀Hbase学习笔记 读取hdfs文件并将sal大于1000的数据保存到hbase中 前置说明&#xff1a; 1.需要配置HadoopConnect 将集群中的/usr/local/soft/hbase-1.4.6/conf/hbase-site.xml复制至Kettle中的 Kettle\pdi-ce-8.2.0.0-342\data-integration\plugins\pentah…

手机投屏到电脑时,手机提示连接失败

前言 注意&#xff0c;本方法建立在你已经通过其他帖子等解决了前置条件的情况下&#xff0c;手机提示连接失败情况下&#xff0c;包括但不限于关闭防火墙、安装无线投屏工具、手机和电脑连接在同一个WiFi频段下、关闭杀毒软件等。 具体操作方法 1、请进入设置 > 系统和…

前端 JS 经典:动态执行 JS

前言&#xff1a;怎么将字符串当代码执行。有 4 中方式实现 eval、setTimeout、创建 script 标签、new Function 1. eval 特点&#xff1a;同步执行&#xff0c;当前作用域 var name "yq"; function exec(string) {var name "yqcoder";eval(string); …

【Git】Windows下使用可视化工具Sourcetree

参考&#xff1a;[最全面] SourceTree使用教程详解(连接远程仓库&#xff0c;克隆&#xff0c;拉取&#xff0c;提交&#xff0c;推送&#xff0c;新建/切换/合并分支&#xff0c;冲突解决&#xff0c;提交PR) 1.Git工具–sourcetree 之前文章介绍过Linux系统中的Git工具&…

如何系统学习vue框架

前言 在软件开发的浩渺星海中&#xff0c;编程规范如同航海的罗盘&#xff0c;为我们指引方向&#xff0c;确保我们的代码之旅能够顺利、高效地到达目的地。无论是个人开发者还是大型团队&#xff0c;编程规范都是提升代码质量、保障项目成功不可或缺的一环。 因此&#xff0c…

Mysql 的分布式策略

1. 前言 MySQL 作为最最常用的数据库&#xff0c;了解 Mysql 的分布式策略对于掌握 MySQL 的高性能使用方法和更安全的储存方式有非常重要的作用。 它同时也是面试中最最常问的考点&#xff0c;我们这里就简单总结下 Mysq 的常用分布式策略。 2. 复制 复制主要有主主复制和…

数据挖掘丨轻松应用RapidMiner机器学习内置数据分析案例模板详解(上篇)

RapidMiner 案例模板 RapidMiner 机器学习平台提供了一个可视化的操作界面&#xff0c;允许用户通过拖放的方式构建数据分析流程。 RapidMiner目前内置了 13 种案例模板&#xff0c;这些模板是预定义的数据分析流程&#xff0c;可以帮助用户快速启动和执行常见的数据分析任务。…

私有化AI搜索引擎FreeAskInternet

什么是 FreeAskInternet FreeAskInternet 是一个完全免费、私有且本地运行的搜索聚合器&#xff0c;并使用 LLM 生成答案&#xff0c;无需 GPU。用户可以提出问题&#xff0c;系统将使用 searxng 进行多引擎搜索&#xff0c;并将搜索结果合并到ChatGPT3.5 LLM 中&#xff0c;并…

微服务之负载均衡器

1、负载均衡介绍 负载均衡就是将负载(工作任务&#xff0c;访问请求)进行分摊到多个操作单元(服务器&#xff0c;组件)上 进行执行。 根据负载均衡发生位置的不同&#xff0c; 一般分为服务端负载均衡和客户端负载均衡。 服务端负载均衡指的是发生在服务提供者一方&#xff…

第十五届蓝桥杯物联网试题(国赛)

好&#xff0c;很好&#xff0c;国赛直接来个阅读理解&#xff0c;我猛做4个小时40分钟&#xff0c;cpu都干冒烟了&#xff0c;也算是勉强做完吧&#xff0c;做的很仓促&#xff0c;没多检查就交了&#xff0c;方波不会&#xff0c;A板有个指示灯没做&#xff0c;其他应该都还凑…