【数据结构】如何应用堆解决海量数据的问题

news2024/11/28 18:45:12

在这里插入图片描述

堆(Heap数据结构堆在计算机科学中有着广泛的应用,今天来介绍两种堆的应用:堆排序、Top-k问题🍉

堆排序

​ 堆排序是一种基于堆数据结构的排序算法。它的基本思想是,将待排序的序列构建成一个大根堆(或小根堆),然后依次取出堆顶元素(即最大值或最小值),将其放入已排序序列的末尾,再将剩余的元素重新调整为一个新的堆。重复这个过程,直到所有元素都被取出并放入已排序序列中。

具体来说,堆排序的过程如下:

  1. 将待排序的长度为n序列构建成一个大根堆(或小根堆)。这个过程可以从最后一个非叶子节点开始,依次向前进行,保证每个子树都是一个大根堆(或小根堆)。
  2. 取出堆顶元素(即最大值或最小值),将其放入已排序序列的末尾。
  3. 将剩余(n-1)的元素重新调整为一个新的堆。
  4. 重复步骤 2 和步骤 3,直到所有元素都被取出并放入已排序序列中。最终得到的序列就是排好序的。

最终得到的序列就是排好序的。

堆排序的时间复杂度为 O(nlogn),空间复杂度为 O(1)。

在这里插入图片描述

向下调整法

从非叶节点的最后一个数据的下标开始,每次取出孩子中较大或较小的数(看是大堆还是小堆)向下进行调整,由于每多一层,下层是上层的二倍,这种办法直接可以省略掉最后一层,也可以达到建堆的目的,所以这种办法为更优的办法。

由于需要向下调整,所以这种办法需要找到子节点,我们已经知道父结点的运算了,子结点就是父节点的逆运算。

结合上面所说,实现代码如下:

void AdjustDown(HeapDataType* arr, int n, int parent)//向下调整
{
	assert(arr);
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child<n - 1 && arr[child] > arr[child + 1])
		{
			child = child + 1;
		}
		if (arr[child] < arr[parent])
		{
			swap(&arr[child], &arr[parent]);
		}
		parent = child;
		child = child * 2 + 1;
	}
}

void HeapSort(int* a,int n)//堆排序
{
	for (int i = (n - 2) / 2; i >= 0; i--)
	{
		AdjustDown(a, n,i);
	}

	for (int i = n-1; i > 0; i--)
	{
		swap(&a[0], &a[i]);
		AdjustDown(a, i, 0);
	}
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
}

int main()
{
	int arr[] = { 1,4,6,2,4,8,5,8,3,111,4,5,32,44 };
	HeapSort(arr, sizeof(arr) / sizeof(int));
}

Top-k问题

Top-k 问题是指在一个数据集中找到前 k 个最大(或最小)的元素。一般情况下数据量都比较大。 比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。

下面是使用堆排序实现 Top-k 问题的具体步骤:

  1. 创建一个大小为 k 的小根堆,用于存储当前的前 k 个最大元素。
  2. 将前 k 个元素插入小根堆中。
  3. 遍历剩余的元素,对于每个元素执行以下操作:
    • 如果当前元素比堆顶元素大,则将堆顶元素弹出,再将当前元素插入堆中。
  4. 遍历完所有元素后,小根堆中剩余的 k 个元素就是前 k 个最大元素。

使用堆排序实现 Top-k 问题的时间复杂度为 O(nlogk),空间复杂度为 O(k),其中 n 是数据集的大小。这种方法适用于数据集较大的情况,但需要额外的空间来存储堆。

代码实现

  • 生成一个有10000随机数的文件
void CreateNDate()	//生成一个有10000个随机数的文件
{
	int n = 10000;
	srand(time(0));
	const char* file = "data.txt";
	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}
	for (int i = 0; i < n; i++)
	{
		int x = rand() % 10000;
		fprintf(fin, "%d\n", x);
	}
	fclose(fin);
}

按上述步骤进行排序

void AdjustDown(HeapDataType* arr, int n, int parent)//向下调整
{
	assert(arr);
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child<n - 1 && arr[child] > arr[child + 1])
		{
			child = child + 1;
		}
		if (arr[child] < arr[parent])
		{
			swap(&arr[child], &arr[parent]);
		}
		parent = child;
		child = child * 2 + 1;
	}
}
void PrintTopK(int k)
{
	const char* file = "data.txt";
	FILE* fin = fopen(file, "r");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}
	int* heap = (int*)malloc(k * sizeof(int));
	int x;
	for (int i = 0; i < 5; i++)
	{
		fscanf(fin,"%d",&heap[i] );//将前k个元素放到数组里
	}
    for (int i = (k - 1 - 1) / 2; i >= 0; i--)	//将k个元素建立一个小堆
	{
		AdjustDown(heap, k, i);
	}
	while (!feof(fin))
	{
		fscanf(fin, "%d", &x);
		if (heap[0] < x)
		{
			heap[0] = x;		//将剩余n-k个元素依次与堆顶元素交换,不满则则替换

			AdjustDown(heap,k,0);
		}
	}
	fclose(fin);
	for (int i = 0; i < k; i++)
	{
		printf("%d  ", heap[i]);
	}
}

int main()
{
	CreateNDate();
	PrintTopK(10);
}

img

✨本文收录于数据结构理解与实现

当你喜欢一篇文章时,点赞、收藏和关注是最好的支持方式。如果你喜欢我的文章,请不要吝啬你的支持,点赞👍、收藏⭐和关注都是对我最好的鼓励。感谢你们的支持!

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

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

相关文章

三展齐发,DBF户外展、高博会、健身展隆重开幕,火爆现场燃炸鹏城!

5月25日&#xff0c;深圳建设国家体育消费试点城市系列活动&#xff0c;第四届DBF深圳国际户外运动博览会&#xff0c;DBF深圳国际高尔夫运动博览会暨深圳国际健身运动博览会&#xff08;以下简称DBF运动户外生活展&#xff09;在深圳国际会展中心5.7号馆盛大举办&#xff01;开…

recurdyn接触特征参数含义

一般接触特征设置 Static Threshold Velocity静态门槛速度&#xff1a;判断静态摩擦和动态摩擦的标准&#xff0c;若相对速度小于此值&#xff0c;摩擦为静摩擦&#xff1b;若相对速度大于此值&#xff0c;摩擦为动摩擦。静态摩擦区域内摩擦系数计算函数为 Dynamic Threshold V…

【网络编程】详解UDP/TCP套接字的创建流程+守护进程

目录 一、网络编程套接字 1、一些概念 1.1源IP地址和目的IP地址 1.2端口号port 1.3TCP和UDP的性质 1.4网络字节序、IP地址类型转换、数据接收与发送函数、popen函数 2、UDP套接字 2.1UDP服务器创建流程 2.2UDP客户端创建流程 2.3创建socket套接字 2.4绑定套接字对应…

模仿抖音直播商城带货打赏功能做一个app系统

随着人们生活和互联网的高度整合&#xff0c;越来越多的人开始转变自身消费模式&#xff0c;从实体店购物逐渐转向足不出户即可享受购物快感的网上购物。许多企业看到了电子商务背后隐藏的巨大价值&#xff0c;想要寻找合适的开发商建立属于自己的电商直播系统&#xff0c;那么…

【新星计划·2023】网工知识——OSPF讲解

OSPF ( Open Shortest Path First开放式最短路径优先)是一种动态路由协议&#xff0c;属于内部网关协议( Interior Gateway Protocol&#xff0c;简称IGP )&#xff0c;是基于链路状态算法的路由协议。 一、OSPF是什么&#xff1f; OSPF意思是指一个内部网关协议(Interior Ga…

阿里云短信验证接口调用

需要的maven依赖 <!-- 升级版 SDK这是一个短信 --> <dependency> <groupId>com.aliyun</groupId> <artifactId>dysmsapi20170525</artifactId> <version>2.0.23</version> </dependency> package com.service.thereServ…

融合改进Sine混沌映射的新型粒子群优化算法(NIPSO)-附代码

融合改进Sine混沌映射的新型粒子群优化算法(NIPSO) 文章目录 融合改进Sine混沌映射的新型粒子群优化算法(NIPSO)1.粒子群优化算法2. 改进粒子群优化算法2.1 改进的 Sine 混沌映射2.2 粒子群改进 3.实验结果4.参考文献5.Matlab代码6.Python代码 摘要&#xff1a;为了应对传统粒子…

vscode remote server tunnel内网穿透转发tcp,速率10kb每秒

参考: vscode网页版的正确打开方式(建立tunnel-p2p连接)_vscode打开网页_怪力左手的博客-CSDN博客 在vps(ubuntu20.04 可出网,无公网ip)上输入如下命令: 需要chisel这个工具,通过websocket转发tcp连接和启动socks5代理, cd /tmp; curl -L -O https://github.com/jpillora/c…

C++异步调用方法

C之future和promise future和promise的作用是在不同线程之间传递数据。使用指针也可以完成数据的传递&#xff0c;但是指针非常危险&#xff0c;因为互斥量不能阻止指针的访问&#xff1b;而且指针的方式传递的数据是固定的&#xff0c;如果更改数据类型&#xff0c;那么还需要…

基于SpringBoot+Vue的搬家服务系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 当今社会&#xff0c;…

实践指南-前端性能提升 270%

目录 一、背景 二、优化前 1. 了解测量工具及性能指标 1.1 Performance 1.2 最佳实践 1.3 SEO 2. 分析需要优化的地方 2.1 Performance 2.2 最佳实践 2.3 SEO 三、优化 Performance 1. 体积优化 1.1 代码压缩 1.2 代码分包 1.3 组件按需加载 1.4 工具库按需加载…

基于SpringBoot+Vue的超市货物管理系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 在1990年代初期&#…

ELK【elasticsearch+logstash+kibana】企业级日志分析系统

文章目录 一、ELK概述1. ELK简介2.ElasticSearch3. Logstash4.Kiabana5.Filebeat6.为什么要用ELK&#xff08;思考一下&#xff09;7.ELK的工作原理 二、ELK实验&#xff08;部署ELK日志分析系统&#xff09;1.关闭防火墙2.安装 Elasticsearch-head 插件 总结 一、ELK概述 1. …

第六章 Matlab的复数数据、字符数据和附加画图类型

在第二章中,我们学习了 MATLAB 基础数据类型:double 和 char。MATLAB 还有许 多的附加数据类型,在本章,我们将会了解它们中的一个。我们要讨论的附加数据类型是 MATLAB 支持的复数数据。我们也将学习如何使用 char 数据类型,以及如何把 MATLAB 数组扩展为多维数组。 本章…

如何使用wireShark的追踪流功能抓取并还原文件

简介 WireShark的追踪流功能可以帮我们抓取从网络上下载的各种文件&#xff0c;接下来就演示下如何抓取并且进行还原。 使用Nginx搭建文件存储服务器 只要是通过http网站下载的包&#xff0c;都可以通过追踪流工具进行抓取。这里为了演示&#xff0c;临时搭建一个Nginx文件存…

Redis的全局命令及相关误区

Redis中所说的数据结构是针对key-value中的value而言的。主要的结构包括String、哈希表、列表、集合等等在redis中存在16个库&#xff0c;涉及到后期的集群搭建只能使用0号库最为方便 查看所有键&#xff08;支持通配符&#xff09; keys * keys S*返回当前数据库中的键总数 …

设计原则-开闭原则

世界上没有任何一个项目是不需要迭代的&#xff0c;随着项目的发展壮大&#xff0c;会有越来越多的功能代码会被修改、添加、删除。据统计线上的生产事故90%都有由于变更引起的&#xff0c;因此为保证项目的迭代稳定性&#xff0c;我们需尽可能的遵守开闭原则。那开闭原则到底是…

Jeston Orin Nano Sdkmanager 自动化安装部署官网CUAD环境

大家好&#xff0c;我是虎哥&#xff0c;入手一块Jeston Orin nano 8G模块&#xff0c;这个模块因为是英伟达未来5年左右主推的模块&#xff0c;所以我逐步会将之前所有的应用都在这个模块环境上做适配&#xff0c;本章内容&#xff0c;我将主要围绕烧写安装系统后&#xff0c;…

R7-13 小明找前缀100000(假)

题目背景 小明最近上课天天睡觉&#xff0c;于是啥都不会。 一天&#xff0c;老师终于点兵点将点到他回答问题&#xff0c;你能帮他渡过难关吗&#xff1f; 现在老师给了小明 n 个由 0、1 构成的字符串&#xff0c;然后有 m 次询问&#xff0c; 每次询问给出一个由 0、1 构…

关于Vue3 ,看这一篇文档你就会用了

随着Vue3的到来&#xff0c;公司的新项目全部进行了升级&#xff0c;相比于Vue2&#xff0c;语法上个人觉得更简洁&#xff0c;更容易通俗易懂。首先安装vue3项目&#xff0c;这里我使用vite进行安装&#xff08;强烈推荐&#xff0c;启动速度贼快&#xff09; npm create vit…