堆的应用:Top-K问题

news2024/11/28 8:27:56

朋友们、伙计们,我们又见面了,本期来给大家解读一下堆的应用--Top-K问题的相关知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成!

数据结构与算法专栏:数据结构与算法

个  人  主  页 :stackY、

C 语 言 专 栏:C语言:从入门到精通

前言:

前面我们学了堆的实现、 堆排序算法,堆排序算法中我们知道了使用堆排序要向下调整建堆排升序我们建的是大堆、排降序我们建小堆,其中的细节就不做赘述,堆排序算法让我们初步了解了堆这种特殊的数据结构的作用,那么在本篇再来给大家带来一个关于堆的应用的问题:Top-K问题

 1.何为Top-K

TopK问题指的是在一个包含N个元素的序列中,找出其中前K个最大或者最小的元素。通常情况下,K远小于N,因此这个问题也被称为“求前K大(小)元素”问题。TopK问题在数据分析、排序算法、搜索引擎等领域都有着广泛的应用。

举个栗子:

在100000个随机数数中找出前10个最大的数。

2.解题思路 

TopK问题在这里有多种解决的办法,我们取最优解:

1. 对N个数据进行从小到大或者从大到小排序,然后取出前K个数据便是我们想要找的数据。

2. 联想我们学过的堆排序,将这N个数建立大堆或者小堆,依次取出前K个数据即可。

但是这两种方法都存在一个问题:首先排序本身就是比较费劲的事情,如果N非常大,排序需要的代价很大,并且将N个数建堆也不合理,因为数据过多计算机内存容纳不下那么多的数据,就会存储到磁盘文件中,我们知道数据在磁盘文件中处理的速度是比较慢的,因此我们需要想一个更方便的方法(假设要在N个数据中找前K个最大的数据)。

改进方法:

1. 先建立K个数的小堆

2. 再用后面N-K个数依次插入,如果比堆顶的数据大,就替换进堆

3. 最后这个小堆中的数据就是要找的前K个数。

3.代码演示 

3.1创建数据

我们为了来演示代码的正确性,我们先来创建数据,将10W个数据先保存在一个文件中,然后找出这10W个数据中最大的前五个数据。这里就需要用到文件操作的相关知识(进阶C语言:文件操作)和一个随机数的种子(猜数字小游戏)。

代码演示:

//创建数据
void CreateNDate()
{
	int n = 100000;           //总数据个数
 	srand((unsigned int)time(NULL));  //设置随机数生成器
	const char* file = "data.txt";
	//打开文件
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen fial");
		return;
	}
	for (int i = 0; i < n; i++)
	{
		//数据范围在10W之内
		int x = rand() % 100000;
		//写文件
		fprintf(fin, "%d\n", x);
	}
	//关闭文件
	fclose(fin);
	fin = NULL;
}

3.2建小堆、排序 

先建K个数的小堆,然后使用剩下的N-K个数据依次插入比较,比堆顶大的数据就替换进堆,然后向下调整,直到将文件中的所有数据比较完成,这时这个K个数的堆就是我们要找的数据(这里建小堆为什么不建大堆?因为小堆的堆顶的元素是这个堆中最小的元素,如果有比它大的就可以筛选进入堆,如果建成大堆,那么堆顶的数就是最大的,那么遇到次大的就进不来,所以需要建小堆)。

代码演示:

void PrintTopK(int k)
{
	//打开文件
	const char* file = "data.txt";
	FILE* fout = fopen(file, "r");
	if (fout == NULL)
	{
		perror("fopen fial");
		return;
	}
	//先建立K个数的小堆
	int* kminheap = (int*)malloc(sizeof(int) * k);
	if (kminheap == NULL)
	{
		perror("malloc fail");
		return;
	}
	//将文件中的前K个数据先储存在块空间中
	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &kminheap[i]);
	}

	//向下调整将这K个数建成小堆
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(kminheap, k, i);
	}

	int num = 0;
	//文件读取结束表示排序完成
	while (!feof(fout))
	{
		//依次比较
		fscanf(fout, "%d", &num);
		//符合则进行替换,向下调整
		if (num > kminheap[0])
		{
			kminheap[0] = num;
			AdjustDown(kminheap, k, 0);
		}
	}

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

	//关闭文件
	fclose(fout);
	fout = NULL;
}

4.完整代码

 

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


//Top - K问题

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

//向下调整
void AdjustDown(int* a, int n, int parent)
{
	//假设左孩子为左右孩子中最小的节点
	int child = parent * 2 + 1;

	while (child < n)  //当交换到最后一个孩子节点就停止
	{
		if (child + 1 < n  //判断是否存在右孩子
			&& a[child + 1] < a[child]) //判断假设的左孩子是否为最小的孩子
		{
			child++;   //若不符合就转化为右孩子
		}
		//判断孩子和父亲的大小关系
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			//更新父亲和孩子节点
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

//创建数据
void CreateNDate()
{
	int n = 100000;           //总数据个数
 	srand((unsigned int)time(NULL));  //设置随机数生成器
	const char* file = "data.txt";
	//打开文件
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen fial");
		return;
	}
	for (int i = 0; i < n; i++)
	{
		//数据范围在10W之内
		int x = rand() % 100000;
		//写文件
		fprintf(fin, "%d\n", x);
	}
	//关闭文件
	fclose(fin);
	fin = NULL;
}

void PrintTopK(int k)
{
	//打开文件
	const char* file = "data.txt";
	FILE* fout = fopen(file, "r");
	if (fout == NULL)
	{
		perror("fopen fial");
		return;
	}
	//先建立K个数的小堆
	int* kminheap = (int*)malloc(sizeof(int) * k);
	if (kminheap == NULL)
	{
		perror("malloc fail");
		return;
	}
	//将文件中的前K个数据先储存在块空间中
	for (int i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &kminheap[i]);
	}

	//向下调整将这K个数建成小堆
	for (int i = (k - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDown(kminheap, k, i);
	}

	int num = 0;
	//文件读取结束表示排序完成
	while (!feof(fout))
	{
		//依次比较
		fscanf(fout, "%d", &num);
		//符合则进行替换,向下调整
		if (num > kminheap[0])
		{
			kminheap[0] = num;
			AdjustDown(kminheap, k, 0);
		}
	}

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

	//关闭文件
	fclose(fout);
	fout = NULL;
}

int main()
{
	//创建数据
	CreateNDate();
	//求前5个最大数
	PrintTopK(5);
	return 0;
}

 可以看到在10W个数据中找到了前5个最大的数。

 

朋友们、伙计们,美好的时光总是短暂的,我们本期的的分享就到此结束,最后看完别忘了留下你们弥足珍贵的三连喔,感谢大家的支持!

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

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

相关文章

基于Web智慧油库三维可视化管理系统

油库是协调原油生产、原油加工、成品油供应及运输的纽带&#xff0c;是国家石油储备和供应的基地&#xff0c;它对于保障国防和促进国民经济高速发展具有相当重要的意义。 建设背景 石油作为重要的战略资源&#xff0c;关系着国家安全和人民生活。油库是石油能源供应链中的关…

俞浩“死磕”抖音,追觅科技618面临三变数

​文 | 智能相对论 作者 | 渡过 智能清洁“新秀”追觅科技来势汹汹。 创始人俞浩曾向媒体表示&#xff0c;“追觅科技……2023年做到行业技术第一&#xff0c;2024年做到行业市占率第一&#xff0c;2025年做到行业利润第一。” 具体到市场上&#xff0c;能拱火热度的电商节…

linux实践php8.2加laravel-cotane和roadrunner服务器

php8.2 composer -v 报错&#xff1a; Deprecation Notice: strlen(): Passing null to parameter #1 ($string) of type string is deprecated in phar:///usr/bin/composer/vendor/symfony/console/Descriptor/TextDescriptor.php:290 解决方法可以升级下composer&#xff1…

像写 Rust 一样写 Python!

几年前&#xff0c;开始使用Rust编程&#xff0c;它逐渐改变了我使用其他编程语言&#xff08;尤其是Python&#xff09;设计程序的方式。在我开始使用Rust之前&#xff0c;我通常以一种非常动态和类型松散的方式编写Python代码&#xff0c;没有类型提示&#xff0c;到处传递和…

2023年江西省大学生程序设计竞赛vp赛后补题

Problem - B - Codeforces 思路&#xff1a; 显然难以讨论<的情况&#xff0c;正难则反&#xff0c;我们尝试计算>的情况以为每次a&#xff0c;他的实际贡献给b的是a%m&#xff0c;x也一样&#xff0c;所以他们先取mod我们能够大于成立&#xff0c;要求a[i]sum>mod,…

常用的表格检测识别方法——表格结构识别方法 (下)

常用的表格检测识别方法——表格结构识别方法&#xff08;下&#xff09; 3.2表格结构识别方法 表格结构识别是表格区域检测之后的任务&#xff0c;其目标是识别出表格的布局结构、层次结构等&#xff0c;将表格视觉信息转换成可重建表格的结构描述信息。这些表格结构描述信息…

深度剖析数据在内存中的存储(超详细版)

&#x1f495;"痛苦难以避免&#xff0c;而磨难可以选择。"-->村上春树&#x1f495; 作者&#xff1a;Mylvzi ​​​​​​​ 文章主要内容&#xff1a;数据在内存中的存储 目录 前言&#xff1a;数据在计算机中的存储 正文&#xff1a; 1.详解数据类型 2.整…

2023-05-31 Git将已存在的项目上传到仓库

背景 正常情况下我们是在GitHub(Gitee是一样的&#xff0c;还不卡&#xff0c;因此下文将在Gitee仓库操作)创建一个代码仓库&#xff0c;然后将仓库拉到本地&#xff0c;在本地会生成一个和仓库名称一样的文件夹&#xff0c;然后在文件夹内写代码&#xff0c;最后使用git命令将…

9 概率图模型【手写笔记】

文章目录 9 概率图模型【手写笔记】9.1 背景介绍9.2 贝叶斯网络&#xff08;Bayesian Network&#xff09;——有向图网络9.3 马尔可夫网络&#xff08;Markov Network&#xff09;——无向图网络9.4 Inferce&#xff08;推断&#xff09;——求解后验9.5 更多的图的概念 9 概率…

2023年DAMA-CDGA/CDGP数据治理认证考试形式、含金量

DAMA认证为数据管理专业人士提供职业目标晋升规划&#xff0c;彰显了职业发展里程碑及发展阶梯定义&#xff0c;帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力&#xff0c;促进开展工作实践应用及实际问题解决&#xff0c;形成企业所需的新数字经济下的核心职业…

表的约束.

目录 表的约束空属性默认值列描述zerofill主键自增长唯一键外键综合案例 表的约束 真正约束字段的是数据类型&#xff0c;但是数据类型约束很单一&#xff0c;需要有一些额外的约束&#xff0c;更好的保证数据的合法性&#xff0c;从业务逻辑角度保证数据的正确性。比如有一个…

一文带你了解MySQL之undo日志

目录 一、事务回滚的需求二、事务id2.1 给事务分配id的时机2.2 事务id是怎么生成的2.3 trx_id隐藏列 三、undo日志的格式3.1 INSERT操作对应的undo日志3.2 DELETE操作对应的undo日志3.3 UPDATE操作对应的undo日志3.3.1 不更新主键的情况3.3.2 更新主键的情况 四、通用链表结构五…

法国ESC高等商学院DBA申请

申请法国ESC高等商学院DBA&#xff0c;你需要了解这些&#xff01;什么是法国ESC高等商学院DBA&#xff1f;法国ESC高等商学院DBA是法国商学院中的顶尖学位&#xff0c;也是全球最优秀的商学博士学位之一。该学位旨在为商业领袖、企业家和高级管理人员提供高水平的商业教育和研…

优秀的工具=生产力!15款高效原型设计软件种草

一个优秀产品的诞生&#xff0c;必定离不开原型设计。产品原型是概念到现实的桥梁&#xff0c;是产品成功的关键&#xff01; 为什么产品原型如此重要&#xff1f;产品原型可以帮助团队更高效地测试产品可行性、理解和评估用户需求并不断优化迭代产品的最终方案。它决定了最终…

windows10系统mysql官方绿色版安装

1.下载 1&#xff09;下载页面&#xff1a;MySQL :: Download MySQL Community Server 2&#xff09;点击 Download 按钮下载zip包到本地&#xff0c;解压&#xff08;我的本地解压到了D:\Programs\mysql-8.0.33-winx64&#xff09; 2.环境配置 1&#xff09;环境变量配置&a…

柜体内形成电弧的四个阶段及弧光保护装置的设计

安科瑞虞佳豪 什么是弧光保护 弧光保护是指电力系统由于各种的短路原因可引起弧光&#xff0c;弧光会以300m/s的速度爆发&#xff0c;摧毁途中的任何物质。只要系统中不断电&#xff0c;弧光就会一直存在。要想最大限度的减少弧光的危害&#xff0c;我们需要安全、迅速地切断…

Java开发手册中为什么禁止使用BigDecimal的equals方法做等值比较已经为什么禁止使用double直接构造BigDecimal

场景 阿里Java开发手册嵩山版中明确指出&#xff1a; 1、BigDecimal的等值比较应使用compareTo()方法&#xff0c;而不是equals()方法 equals()方法会比较值和精度&#xff08;1.0与1.00返回结果为false&#xff09;,而compareTo()则会忽略精度 2、禁止使用构造方法BigDeci…

FAQ是什么?如何打造一个高效的FAQ页面?

FAQ是英文Frequently Asked Questions的缩写&#xff0c;即“常见问题解答”。FAQ系统是一个集中管理和展示常见问题和答案的工具。 FAQ页面一般放在网站的主菜单或底部导航栏中&#xff0c;通常与“联系我们”、“关于我们”等页面并列。有些网站还会在页面上方或右侧设置“常…

android开发之NDK配置开发

1、打开项目后&#xff0c;一次点击Tools>SDK Manager 2、点击SDK Tools标签页 3、选中NDK&#xff08;Side by Side&#xff09;和CMake复选框 4、点击OK 此时系统会显示一个对话框&#xff0c;告诉你NDK软件包占用了多少磁盘空间 5、点击OK 6、安装完成后&#xff0c;点击…

Web3 游戏的用户留存的挑战与机遇:从经济模型与游戏设计谈起

作者&#xff1a;lesleyfootprint.network 在开发和运营 Web3 游戏时&#xff0c;会面临许多挑战&#xff0c;因此有效地应对这些挑战对游戏的成功至关重要。其中一些策略包括在正式发布之前进行全面测试&#xff0c;并持续提供新的游戏玩法和内容&#xff0c;以确保游戏经济系…