堆排序及top k 问题

news2024/10/6 12:28:23

目录

一:堆排序

1.向上调整建堆

2.向下调整建堆

3.向上调整建堆时间复杂度 

4.向下调整建堆时间复杂度 

二:找 top k 问题

1.造数据

2.进行建堆,查找最大的K个数据


一:堆排序


升序 --- 建大堆 --- 每个父亲节点 >= 孩子节点

降序 --- 建小堆 --- 每个父亲节点 <= 孩子节点 

 在此处我们需要一个堆,参考http://t.csdn.cn/GDbI9

在上述链接中建立的为小堆。

小堆 --- 选出最小的,然后进行首尾交换,将最小的一个放在最后一个位置。

然后,把最后一个不看作堆里面的。向下调整,选出次小的数据,循环往反上述过程。


1.向上调整建堆


//建堆
int i = 0;
//向上调整建堆
for (i = 0; i < n; i++)
{

//传入数组  孩子的下标
     AdjustUp(a, i);
}

//在下一个数据插入时,已经为堆(前面的值可以构成堆)

 


 代码为:

//堆排序
void HeapSort(int* a, int n)
{
	//升序 --- 建大堆
	//降序 --- 建小堆
	 	
	//建堆
	int i = 0;
	//向上调整建堆
	for (i = 0; i < n; i++)
	{
		AdjustUp(a, i);
	}

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

	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		//在调整 --- 选出次小的数
		AdjustDown(a, end, 0);
		--end;
	}
}
int main()
{
	int a[10] = { 1,2,3,4,5,6,8,7,9,0};
	int n = sizeof(a) / sizeof(a[0]);
	HeapSort(a, n);
}

 运行效果为:

2.向下调整建堆


 //向下调整建堆
for (i = (n - 1 - 1) / 2; i >= 0; i--)
{

//传入 数组 数组的大小 数组下标
   AdjustDown(a, n, i);
 }

//父亲节点 = (孩子节点 - 1 ) / 2 

//从倒数第一个非叶节点开始调

 


 代码为:

//堆排序
void HeapSort(int* a, int n)
{
	//升序 --- 建大堆
	//降序 --- 建小堆
	 	
	//建堆
	int i = 0;
	向上调整建堆
	//for (i = 0; i < n; i++)
	//{
	//	AdjustUp(a, i);
	//}

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

	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		//在调整 --- 选出次小的数
		AdjustDown(a, end, 0);
		--end;
	}
}
int main()
{
	int a[10] = { 1,2,3,4,5,6,8,7,9,0};
	int n = sizeof(a) / sizeof(a[0]);
	HeapSort(a, n);
}

运行效果为:

3.向上调整建堆时间复杂度 

4.向下调整建堆时间复杂度 

二:找 top k 问题

即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
假设:有N个数,找其中得最大/最小的 K 个数
方案一:
将N个数建成一个大堆,Pop K次,即可以求出最大的前K个,该方法在N特别大的时候,解决不了问题。
 
方案二:
将前K个数建立一个小堆
后面的N-K个数,依次比较,如果比堆顶数据大,就替换堆顶数据进堆(覆盖堆顶数据,向下调整)
最后这个小堆的值,就是前K个

1.造数据


需要先造出N个数据

CreateNDate();


产生随机数的函数:srand

获取系统时间:time

 在造数据的时候,我们可以将所造的数据存储在一个文件中 --- data.txt

关于文件操作,可以参考:http://t.csdn.cn/qejfU

代码为:

//找 topK 问题
void CreateNDate()
{
	// 造数据
	int n = 10000;
	srand(time(0));
	const char* file = "data.txt";

	//fopen --- 打开文件
	//FILE *fopen( const char *filename, const char *mode );
	//              文件名                  打开方式

	FILE* fin = fopen(file, "w");
	if (fin == NULL)
	{
		perror("fopen error");
		return;
	}

	for (size_t i = 0; i < n; ++i)
	{
		//rand --- 获取随机数
		//int rand( void );

		int x = rand() % 1000000;

		//fprintf --- 向文件写入格式化的内容
		//int fprintf( FILE *stream, const char *format [, argument ]...);
		//对比 printf 函数 
		//int printf( const char *format [, argument]... );

		fprintf(fin, "%d\n", x);
	}

	//fclose --- 关闭文件
	//int fclose( FILE *stream );
	//             目标文件

	fclose(fin);
}

int main()
{
	CreateNDate();

	//PrintTopK(8);
	return 0;
}

 结果为:

 生成的数据

2.进行建堆,查找最大的K个数据


需要先以只读的方式,打开数据所在的 --- data.txt ,然后读取(fscanf)前K个数据将其采用向下调整建堆的方式放在一个数组中(在此处,需要先开辟好一个数组用于存放数据),然后依次去读取剩下的N-K个数据,让其分别于堆顶数据(堆顶数据为堆内最小的数据 --- 小堆)进行比较,如果比堆顶数据大,则覆盖堆顶数据,然后进行向下调整算法,然后打印出数组中的内容,以上操作进行完毕后,关闭文件。


代码为:

//向下调整算法
//在此处先设计改为小根堆 --- 每个父亲都 <= 孩子 
void AdjustDown(int* a, int* n, int parent)
{
	//对其逻辑结构进行分析,如果没有左孩子,则一定没有右孩子
	int child = parent * 2 + 1;//左孩子
	while (child < n)
	{
		//找到左右孩子中的较小孩子 --- 判断右孩子存在
		//                             有左孩子不一定有右孩子 --- 右孩子要先存在,才能与左孩子进行比较,注意写代码时的顺序
		if ( child + 1 < n && a[child] > a[child + 1])//左孩子大于右孩子,则 child 为右孩子,上述假设时,假设的为左孩子小
		{
			++child;
		}

		//找到较小的孩子,与父亲节点进行比较,若比其小,让其与其父亲节点进行交换
		if (a[parent] > a[child])
		{
			Swap(&a[parent], &a[child]);//让小的节点向上走,大节点向下走
			parent = child;
			child = parent * 2 + 1;//循环更替条件
		}
		else
		{
			break;
		}
	}
}

void PrintTopK(int k)
{
	//先建立一个小堆,存放 k 个数据,然后用其他数据与堆顶数据做对比,如果比堆顶数据大,将堆顶覆盖
	//小根堆:每个父亲结点 <= 孩子结点

	//以读的方式打开
	const char* file = "data.txt";
	FILE* fout = fopen(file,"r");
	if (fout == NULL)
	{
		perror("fopen error");
		return;
	}
	//读取k个数据放到数组里面 --- 开辟数组用于存放
	int* kminheap = (int*)malloc(sizeof(int) * k);
	if (kminheap == NULL)
	{
		perror("malloc fail\n");
		return;
	}
	int i = 0;
	for (i = 0; i < k; i++)
	{
		fscanf(fout, "%d", &kminheap[i]);
	}

	//建小堆
	for (i = (k - 1 - 1); i >= 0; i--)
	{
		//进行调整
		AdjustDown(kminheap,k,i);
	}
	int val = 0;
	while (!feof(fout))
	{
		fscanf(fout, "%d", &val);
		if (val > kminheap[0])
		{
			kminheap[0] = val;
			AdjustDown(kminheap, k, 0);

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

	fclose(fout);
}

效果为:

 为了验证其是否为文件中的最大值,我们可以堆 data.txt 的部分数据修改并且屏蔽掉造数据的过程 --- 在此处我们修改最后10个数据:

由此可以知道,我们所取出的数据为文件中的最大的K个数据 --- 此处K为8。

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

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

相关文章

高德API JS 高德地图获取多个坐标点的中心点

高德API JS 高德地图获取多个坐标点的中心点 一、需求 我需要在地图上展示多个地点&#xff0c;并且展示的同时&#xff0c;地图缩放到合适的大小&#xff0c;要求刚好能显示全部点位&#xff0c;并且边缘留有一部分间隔。 做成如图所示这样。 二、需要用到的 AMap 类库 经…

使用Python绘制6.1儿童节消消乐,素描图,词云图,字符画图,提取轮廓图及蒙太奇效果图

这篇博客将介绍如何使用Python绘制6.1儿童节消消乐&#xff0c;素描图&#xff0c;词云图&#xff0c;字符画图&#xff0c;提取轮廓图及蒙太奇效果图。 使用Python绘制端午dragboat消消乐 美轮美奂的界面效果 1. 效果图 6.1儿童节快乐原始图VS素描图&#xff1a; 素描进阶…

内网穿透-公网ip-方法总结-访问内网服务器-frp-虚拟服务器

文章目录 1.固定IP2.虚拟服务器转发3.IP盒子4.总结 1.固定IP 第一种方式是向三大电信服务商购买专用通道&#xff0c;固定IP&#xff0c;这种方式是最正统&#xff0c;也是各大虚拟服务器服务商采用的方式&#xff0c;宽带带宽有稳定的保障。在访问量不足的前提下&#xff0c;…

anaconda 安装_Linux系统上

安装流程 1 下载安装包 官网 https://www.anaconda.com/download#downloads 2 执行安装 bash Anaconda3-2021.11-Linux-x86_64.sh3 安装过程 一路enteryes&#xff0c;接受licence、指定安装路径和init之后安装完成。 检验anaconda是否安装成功。 conda --version或 con…

【LeetCode】12,整数转罗马数字。 难度等级:中等。易错点:使用 python 字典构建哈希表时要考虑哈希表是否有序

文章目录 一、题目二、我的解法&#xff1a;基于有序哈希表的贪心算法2.1 使用 dict 构建哈希表2.2 使用两个 list / tuple 构建有序哈希表 一、题目 二、我的解法&#xff1a;基于有序哈希表的贪心算法 2.1 使用 dict 构建哈希表 贪心法则&#xff1a;我们每次尽量使用最大的…

基于AT89C52单片机的多功能万年历设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/87853675 源码获取 目 录 摘 要 1 1 方案论证 2 1.1 单片机芯片的选择方案和论证 2 1.2 显示模块选择方案和论证 2 1.3 时钟芯片的选择方案和论证 3 1.4 电路设计…

BitLocker加密卷“恢复密钥(数字密码)”提取还原

BitLocker是微软Windows自带的用于加密磁盘分卷的技术。 通常&#xff0c;解开后的加密卷通过Windows自带的命令工具“manage-bde”可以查看其恢复密钥串&#xff0c;如下图所示&#xff1a; 如图&#xff0c;这里的数字密码下面的一长串字符串即是下面要提取恢复密钥。 在计…

IMA/EVM完整性检测代码分析

IMA/EVM完整性检测 IMA&#xff08;Integrity Measurement Architecture&#xff09;是一个内核安全子系统&#xff0c;用于检测文件或数据的完整性和安全性。IMA的hook机制指的是内核接口钩子&#xff08;kernel interface hooks&#xff09;&#xff0c;用于向IMA注册和实现…

第三章 部署Web及WDS服务

♥️作者介绍&#xff1a;奇妙的大歪 ♥️个人名言&#xff1a;但行前路&#xff0c;不负韶华&#xff01; ♥️个人简介&#xff1a;云计算网络运维专业人员 目录 一.什么是web 1.www(world wide web)万维网 世界 维度 2.www服务软件 3.info…

ElementUI-Form表单二次封装

一、Form组件二次封装考虑组件构成&#xff1a; form组件&#xff1a;input text passworldselectcheckboxradio文本域日期 二、实现Form表单的二次封装&#xff1a; 1. 分析出对应的位置 开始抽离组件 2. 如果需要产生多个form表单&#xff0c;则需要产生多个el-form-item…

学习路之gis--百度离线地图下载制作

在有些情况下需要使用地图&#xff0c;但又不能访问外网&#xff0c;这时你需要一个离线地图。本文介绍如何制作百度离线地图。 下面将介绍如何实现一个离线版百度地图&#xff1a; 1. 下载百度地图瓦片 下载网址&#xff1a;望远网-百度地图下载 首先需选择下载地图瓦片的样式…

BUG: scheduling while atomic: fpv_cams/605/0x00010001

IIO框架下IMU驱动的接口在定时器中断内调用报错&#xff0c;因调用IO读定时间较长会导致睡眠的发生&#xff0c;因为内核总是崩。 尝试了几种解决方法&#xff1a; 1.在IIO框架里&#xff0c;使用 spidev 的接口来读写&#xff0c;错误依旧&#xff1b; 2.去掉IIO框架&#x…

香橙派One(全志H3芯片)编译烧写U-boot、Linux内核zImage、dtb

一、编译烧写u-boot 1.1 源码和工具下载&#xff1a; 香橙派提供了u-boot源码和交叉编译链工具&#xff1a; &#xff08;1&#xff09;u-boot&#xff08;2020.04&#xff09;下载地址&#xff1a;https://github.com/orangepi-xunlong/u-boot-orangepi &#xff08;2&#…

MyBatis - MyBatis Generator

文章目录 1.什么是 MyBatis Generator2.使用 MyBatis Generator2.1 导入依赖2.2 application 配置2.3 添加 Java 配置2.4 MBG 配置2.5 生成代码2.6 基本 CRUD 操作 3.进阶使用 MyBatis Generator3.1 基于条件的 CRUD3.2 子查询、Group 与 Join 查询3.3 一对一查询、一对多查询 …

ANSYS Workbench中的网格优化方法

自 50 年代后期以来&#xff0c;有限元法 (FEM) 已被用作解决工程问题的强大工具。当时的计算是手工进行的&#xff0c;该方法是基于力的&#xff0c;而不是我们今天使用的基于位移的方法。由于计算机工业的进步&#xff0c;已经开发出各种有限元商业软件。Ansys 可以被认为是全…

Nginx网站部署

Nginx网站部署 一、访问状态统计配置二、基于授权的访问控制三、基于客户端的访问控制四、基于域名的 Nginx 虚拟主机五、基于IP 的 Nginx 虚拟主机六、基于端口的 Nginx 虚拟主机 一、访问状态统计配置 1.先使用命令/usr/local/nginx/sbin/nginx -V 查看已安装的 Nginx 是否包…

常用抓包工具使用-wireshark使用(二)

常用抓包工具使用-wireshark使用&#xff08;二&#xff09; 文章目录 常用抓包工具使用-wireshark使用&#xff08;二&#xff09;前言一、wireshark安装1.1 windows安装1.2 mac安装 二、wireshark抓包和过滤2.1 打开Wireshark2.2 选择网络接口&#xff1a;2.3 wireshark抓包页…

【Nginx 网络服务】

目录 一、Nginx和Apache的优点和缺点二、编译安装Nginx服务1.关闭防火墙&#xff0c;将安装nginx所需软件包传到/opt目录下2.安装依赖包3.创建运行用户、组4.编译安装Nginx5.检查、启动、重启、停止 nqinx服务 三、认识Nginx服务的主配置文件 nginx.conf1、系统文件支持数量2&a…

商场内怎么导航?商场导航图怎么画?

商场内怎么导航&#xff1f;大型购物商场是目前一二线城市最常见的购物场所&#xff0c;占地面积较大&#xff0c;布局错综复杂&#xff0c;商品比较齐全&#xff0c;如果没有商场地图导航&#xff0c;会导致新顾客难以找到想要的商品&#xff0c;那么大型购物商场商场地图怎么…

索引特性.

目录 没有索引&#xff0c;可能会有什么问题认识磁盘MySQL与存储先来研究一下磁盘在看看磁盘中一个盘片扇区定位扇区结论磁盘随机访问(Random Access)与连续访问(Sequential Access) MySQL 与磁盘交互基本单位建立共识索引的理解建立测试表插入多条记录查看插入结果中断一下---…