数据结构 ——— 用堆解决TOP-K问题

news2024/11/7 7:41:29

目录

何为TOP-K问题

用堆解决TOP-K问题

代码实现 


何为TOP-K问题

比如:整个专业的前10名,世界500强,富豪榜,游戏中前100的活跃玩家等

对于 TOP-K 问题,能想到的最简单直接的方式就是排序
但是,如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)
最佳就是用堆来解决


用堆解决TOP-K问题

1. 用数据集合中前K个元素来建堆

  • 找前K个最大的元素时,就建小堆
  • 找前K个最小的元素时,就建大堆

2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素

  • 将剩余N-K个元素依次与堆顶元素比完之后
  • 堆中剩余的K个元素就是所求的前K个最大或者最小的元素

代码实现

生成一个数组,并且随机放入 10 个最大的值:

void TestTopK()
{
	// 动态申请 10000 个 int 类型的数组
	int n = 10000;
	int* a = (int*)malloc(sizeof(int) * n);

	// 判断是否申请成功
	if (a == NULL)
	{
		perror("malloc fail");
		return;
	}
	
	// 随机值生成器
	srand((unsigned int)time(NULL));

	// 在数组中依次存放小于 100000 的值
	for (int i = 0; i < n; i++)
	{
		a[i] = rand() % 100000;
	}

	// 将数组中的 10 个元素改为大于或者等于 100000 的值
	a[5] = 100000 + 1;
	a[123] = 100000 + 9;
	a[531] = 100000 + 2;
	a[4121] = 100000 + 8;
	a[115] = 100000 + 3;
	a[2335] = 100000 + 7;
	a[9999] = 100000 + 4;
	a[76] = 100000 + 6;
	a[423] = 100000 + 5;
	a[3144] = 100000 + 0;

	// 找出数组 a 中前 10 个最大的值,并打印
	PrintTopK(a, n, 10);
}

找出前 10 个最大的值:

void PrintTopK(int* a, int size, int k)
{
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		// 向下调整建堆(建小堆)
		AdjustDown(a, k, i);
	}

	for (int i = k; i < size; i++)
	{
		// 当前堆顶元素小于当前数组元素时就交换
		if (a[0] < a[i])
		{
			Swap(&a[0], &a[i]);

			// 向下调整堆
			AdjustDown(a, k, 0);
		}
	}

	ArrPrint(a, k);
}

代码解析(代码中的函数实现会放在最后,先讲解思路):

想要找到数组 a 中的前 10 个最大的数,那么就先建立大小为 10 的小堆
利用向下调整算法对数组 a 中的前 10 个数进行建堆,注意是建小堆
再把数组中剩余的元素依次与堆顶元素比较,当堆顶元素小于数组当前元素时,就交换
因为小堆的特点是:堆顶的元素是整个堆中元素最小的
那么堆中最小元素和数组当前元素比较时,还要小,那么堆顶元素必然不是前 10 个最大的数
交换后再利用向下调整算法调整堆
遍历完数组 a 中的所有元素后,堆中的元素就是前 10 个最大的数

代码验证:

                                               100000
                                      /                               \
                         100002                                   100001
                        /             \                                /            \
            100003              100005         100004              100006
            /         \                 /
   100007 100009      100008 

代码中的函数实现:

// 向下调整(默认小堆)
void AdjustDown(HPDataType* a, int size, int parent)
{
	int child = parent * 2 + 1;

	while (child < size)
	{
		// 先找到左右孩子中小的那个
		if ((child + 1 < size) && (a[child + 1] < a[child]))
			child++;

		if (a[parent] > a[child])
		{
			// 交换
			Swap(&a[parent], &a[child]);
			
			// 迭代
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

// 交换
void Swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

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

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

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

相关文章

开发之翼:划时代的原生鸿蒙应用市场开发者服务

前言 随着"纯血鸿蒙" HarmonyOS NEXT在原生鸿蒙之夜的正式发布&#xff0c;鸿蒙生态正以前所未有的速度蓬勃发展。据知已有超过15000个鸿蒙原生应用和元服务上架&#xff0c;覆盖18个行业&#xff0c;通用办公应用覆盖全国3800万多家企业。原生鸿蒙操作系统降低了接…

WAF+AI结合,雷池社区版的强大防守能力

网上攻击无处不不在&#xff0c;为了保护我自己的网站&#xff0c;搜索安装了一个开源免费的WAF 刚安装完成就收到了海外的攻击&#xff0c;看到是海外的自动化攻击工具做的 雷池刚好也有AI分析&#xff0c;于是就尝试使用这个功能&#xff0c;看看这个ai能力到底怎么样 以下…

Elasticsearch —— ES 环境搭建、概念、基本操作、文档操作、SpringBoot继承ES

文章中会用到的文件&#xff0c;如果官网下不了可以在这下 链接: https://pan.baidu.com/s/1SeRdqLo0E0CmaVJdoZs_nQ?pwdxr76 提取码: xr76 一、 ES 环境搭建 注&#xff1a;环境搭建过程中的命令窗口不能关闭&#xff0c;关闭了服务就会关闭&#xff08;除了修改设置后重启的…

CSP2024 游记

又是一年 CSP。。。 10 月 5 日&#xff0c;终于过 S 初赛了。。。 然后开始漫长的备战。。 在考试开始前 1 day&#xff0c;我还在兢兢业业地学习图论。然后发现没有考。。。 10 月 25 日下午 15:30&#xff0c;来到 CQBS 试机。我想&#xff0c;怎么测试性能呢&#xff1…

opencv - py_imgproc - py_grabcut GrabCut 算法提取前景

文章目录 使用 GrabCut 算法进行交互式前景提取目标理论演示 使用 GrabCut 算法进行交互式前景提取 目标 在本章中 我们将了解 GrabCut 算法如何提取图像中的前景我们将为此创建一个交互式应用程序。 理论 GrabCut 算法由英国剑桥微软研究院的 Carsten Rother、Vladimir K…

视频制作软件新手必备:8款剪辑工具剪辑思路分享!

随着视频的高度发展&#xff0c;视频已成为一种重要的工具&#xff0c;用以学习娱乐、记录生活点滴以及传递各类信息。不论是制作个人MV、进行企业宣传&#xff0c;还是创作短视频内容&#xff0c;拥有一款功能恰当的视频剪辑软件都显得至关重要。对于初学者而言&#xff0c;选…

无人机避障——路径规划篇(一) JPS跳点搜索算法A*算法对比

JSP 跳点搜索算法与改进 A*算法对比 一、算法概述: 跳点搜索(Jump Point Search,JPS)算法:一种用于路径规划的启发式搜索算法。它主要用于在网格地图(如游戏地图、机器人运动规划地图等)中快速找到从起点到终点的最短路径。该算法在改进 A*算法的基础上进行了优化,通过跳过一…

解决Linux安装Anaconda后出现的conda: command not found问题

参考链接&#xff1a;解决Linux安装Anaconda后出现的conda: command not found问题-百度开发者中心

AI直播带货场景切换模块的搭建!

AI直播带货&#xff0c;作为电商领域的新宠&#xff0c;正以其独特的魅力和高效的营销手段&#xff0c;引领着销售模式的新变革。 在AI直播带货中&#xff0c;场景切换模块是不可或缺的一部分&#xff0c;它不仅能够提升观众的观看体验&#xff0c;还能更好地展示商品&#xf…

15 Docker容器存储架构:docker存储驱动简介

文章目录 一、Docker 存储驱动探索1.1 存储驱动1.2 存储驱动方式1.3 非持久化存储1.4 持久化存储一、Docker 存储驱动探索 1.1 存储驱动 Storage driver处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户提供了多层数据合并后的统一视图。 [superman@docker ~]$…

Aicbo:一键生成高质量画作,适合初学者的AI绘画助手

越来越多的智能工具开始进入人们的视野&#xff0c;它们不仅简化了创作流程&#xff0c;还极大地提高了作品的质量。在这一背景下&#xff0c;Aicbo作为一款新兴的AI绘画工具&#xff0c;以其独特的优势和免费试用的政策&#xff0c;迅速获得了广泛的关注和好评。本文将从多个角…

STM32 从0开始系统学习5

目录 STM32 GPIO输入的四种模式 Practice And Usage 练习与封装 Detailed And Reference 更加具体的说明 输入浮空模式 输入上拉模式 输入下拉模式 模拟功能 我们下面聊一聊输入的事情&#xff0c;输入指的是我们的处理器从外部端口接受外设发过来的信号。在我们没有接…

使用Git进行版本控制的最佳实践

文章目录 Git简介基本概念仓库&#xff08;Repository&#xff09;提交&#xff08;Commit&#xff09;分支&#xff08;Branching&#xff09; 常用命令初始化仓库添加文件提交修改查看状态克隆仓库分支操作合并分支推送更改 最佳实践使用有意义的提交信息定期推送至远程仓库使…

冒泡排序和二分查找--go

冒泡排序的逻辑 二分查找的逻辑 func bubbleSort(arr *[5]int){//冒泡排序fmt.Println(*arr)temp : 0for j : len(*arr); j > 0; j-- {for i : 0; i < j-1; i {temp (*arr)[i]if((*arr)[i] > (*arr)[i1]){(*arr)[i] (*arr)[i1](*arr)[i1] temp}}} }func binaryF…

flutter区别于vue的写法

View.dart 页面渲染&#xff1a; 类似于vue里面使用 <template> <div> <span> <textarea>等标签绘制页面, flutter 里面则是使用不同的控件来绘制页面 样式 与传统vue不同的是 flutter里面没有css/scss样式表&#xff0c; Flutter的理念是万物皆…

电影《焚城》全国上映 王丹妮诠释新时代女性力量

今日&#xff0c;电影《焚城》全国上映&#xff0c;该片由刘德华、白宇、莫文蔚和王丹妮主演&#xff0c;以一场由高强度放射性物质铯137泄漏引发的城市灾难为背景&#xff0c;深刻描绘了人们在生死存亡关头的抉择与抗争。 王丹妮在片中饰演飒爽独立、智慧勇敢的消防队长Madam …

uniapp:启动界面关闭时长控制

代码控制关闭启动界面 App启动后不会自动关闭启动界面&#xff0c;需要在代码中调用plus.navigator.closeSplashscreen关闭启动界面。"app-plus" : {"splashscreen" : {"alwaysShowBeforeRender" : false,"autoclose" : false,}, }很多…

Three.js 快速入门构建你的第一个 3D 应用

![ 开发领域&#xff1a;前端开发 | AI 应用 | Web3D | 元宇宙 技术栈&#xff1a;JavaScript、React、Three.js、WebGL、Go 经验经验&#xff1a;6年 前端开发经验&#xff0c;专注于图形渲染和AI技术 开源项目&#xff1a;github 晓智元宇宙、数字孪生引擎、前端面试题 大家好…

二:java 基础知识(2)-- 初始java/语法基础

目录 idea中文插件 第一个 Java 程序 Java数据类型&#xff0c;常量与变量 1. 数据类型 1.1 基本数据类型 1.2 引用数据类型 2. 常量 2.1 特性 2.2 定义常量 ​编辑 3. 变量 3.1 变量的定义与初始化 3.2 变量的类型 局部变量&#xff1a;在方法内声明的变量&#xff0…

【AAOS】【源码分析】CarSystemUI -- CarSystemBar

CarSystemBar不像Android手机那样固定的顶部“状态栏”和底部“导航栏”,而是将StatusBar和NavigationBar都统称为SystemBar,可以通过如下配置为每侧最多配置一个“系统栏”。 packages/apps/Car/SystemUI/res/values/config.xml<!-- Configure which system bars should …