《堆排序》与《Top—k》

目录

​编辑

前言:

关于《堆排序》:

第一步:建堆

第二步:排序

《Top—K问题》

关于Top—k问题:


前言:

我们在前面的blog中,对于《堆》已经有了初步的概念,那么接下来我们可以利用《堆》来解决我们日常生活中存在的问题,本篇我们给出两个常用的应用场景,分别是《排序》以及《Top—k问题》,上一篇blog在:《堆》的模拟实现-CSDN博客

 

关于《堆排序》:

#define _CRT_SECURE_NO_WARNINGS  1
#include<stdio.h>void swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}void AdjustDown(int* arr, int sz, int parent)
{int child = parent * 2 + 1;while (child < sz){if (child + 1 < sz && arr[child] < arr[child + 1]){child++;}if (arr[child] > arr[parent]){swap(&arr[child], &arr[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}void AdjustUp(int* arr, int sz, int child)
{while (child > 0){int parent = (child - 1) / 2;if (arr[parent] < arr[child]){swap(&arr[parent], &arr[child]);}child = parent;}
}int main()
{int arr[] = { 2, 6, 9, 3, 1, 7 };int sz = sizeof(arr) / sizeof(arr[0]);for (int i = (sz - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr, sz, i);}//向下调整算法//for (int i = 1; i<sz; i++)//{//	AdjustUp(arr, sz, i);//}//向上调整算法int end = sz - 1;while (end > 0){swap(&arr[0], &arr[end]);AdjustDown(arr, end, 0);--end;}return 0;
}

第一步:建堆

利用《堆》可以方便我们对一个给定的乱序数组实现排序,首先我们应当选择大堆来进行排序操作。

为什么我们不选择使用小堆来进行建堆呢?

通过之前对《堆》的blog说明,小堆就是对顶元素为最小元素,其他的节点数都比第一个元素小,那么如果是小堆,最小的数字已经就是第一个元素,若要找出次小的元素,则又需要在剩下的元素中再进行建堆,重复循环才能完成排序,这样子的时间复杂度高,不利于排序。

因此我们选择利用大堆来建堆,实现大堆后,再将首尾的元素进行交换,再利用向下调整法调整法对剩下的n-1个元素进行调整,再进行交换,如此能实现排序。

    int arr[] = { 2, 6, 9, 3, 1, 7 };int sz = sizeof(arr) / sizeof(arr[0]);for (int i = 1; i<sz; i++){AdjustUp(arr, sz, i);}

对如图的数组进行向上 调整法建堆:

 

第二步:排序

 首先我们将首尾元素进行交换:

对除最后一个元素外的其他元素进行向下调整法,将其继续成大堆

 

 

 

 

重复上述步骤

最终可得堆为:

 

如此则完成了堆排序。

 

《Top—K问题》

关于Top—k问题:

即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大

比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。我们以求n个数据中前K个最大的元素为例进行说明:(假设n=10000) (假设k=10)

 

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
const char* file = "data.txt";
void swap(int* a, int* b)
{int tmp = *a;*a = *b;*b = tmp;
}void AdjustDown(int* arr, int sz, int parent)
{int child = 2 * parent + 1;while (child < sz){if (child + 1 < sz && arr[child + 1] < arr[child]){child++;}if (arr[child] < arr[parent]){swap(&arr[child], &arr[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}void CreateFile()
{//创建随机数的种子srand((unsigned int)time(NULL));FILE* Fin = fopen(file, "w");if (Fin == NULL){perror("Fopen error");exit(-1);}int n = 10000000;for (int i = 0; i < n; i++){int x = (rand() + i) % n;fprintf(Fin, "%d\n", x);}fclose(Fin);Fin = NULL;
}void Print()
{FILE* Fout = fopen(file, "r");if (Fout == NULL){perror("Fout error");exit(-1);}//取前k个数进小堆int* minheap = (int*)malloc(sizeof(int) * 5);if (minheap == NULL){perror("minheap -> malloc");return;}for (int i = 0; i < 5; i++){fscanf(Fout, "%d", &minheap[i]);}for (int i = (5-1-1)/2; i >=0; --i){AdjustDown(minheap, 5, i);}//读取数据int x = 0;while (fscanf(Fout, "%d", &x) != EOF){if (minheap[0] < x){minheap[0] = x;}AdjustDown(minheap, 5, 0);}for (int i = 0; i < 5; i++){printf("%d ", minheap[i]);}fclose(Fout);Fout = NULL;
}int main()
{//CreateFile();Print();return 0;
}

首先我们先创建10000000个随机数,再对其中的数字进行修改,随机抽5个数,分别修改为

10000001,10000002,10000003,10000004,10000005

再建一个小堆,注意,这里一定是小堆!

如果建的是大堆,若数据先搜索到了10000005,那么该数字一定是在堆顶,当我们查找到次小的数字后,却无法进堆,所以我们采用小堆!

 然后将数据的前5个元素进入小堆中,

再对剩下的9999995个数进行遍历和比较,若大于堆顶元素,则直接替换。

替换完后再进行一次向下调整,当遍历完整个数据后,堆中就是插入的

 10000001,10000002,10000003,10000004,10000005

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

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

相关文章

flex布局(2)

五、优缺点 优点&#xff1a; 简单易用&#xff1a;Flex布局使用简单&#xff0c;只需通过设置容器的属性即可实现弹性布局&#xff0c;无需复杂的计算和调整。自适应性&#xff1a;Flex布局可以根据容器的大小自动调整元素的位置和大小&#xff0c;适应不同的屏幕尺寸和设备…

3.5 RESOURCE ASSIGNMENT

一旦内核启动&#xff0c;CUDA运行时系统将生成相应的线程网格。正如上一节所讨论的&#xff0c;这些线程被分配给逐个块执行资源。在当前一代硬件中&#xff0c;执行资源被组织成流式多处理器&#xff08;SM&#xff09;。图3.12说明可以为每个SM分配多个线程块。每个设备都对…

uniapp中uview组件库中丰富的LineProgress 线形进度条 的使用方法

目录 平台差异说明 #基本使用 #设置进度条动画效果 #设置进度条内部显示百分比值 #修改进度条的样式 #API #Props #Slots 平台差异说明 AppH5微信小程序支付宝小程序百度小程序头条小程序QQ小程序√√√√√√√ #基本使用 通过percent设置当前的进度值&#xff0c;该…

计算机视觉下的数据增强代码实现

数据增强的实现 使用经典的pytorch框架下的torchvision.transformers对计算机视觉进行增强的代码实现。 使用下面的图像进行数据增强&#xff0c;相应的效果图如下所示&#xff01; 导包 import os import PIL.Image as Image from torchvision import transforms as transfor…

RT-Thread 线程间同步 信号量

线程间同步 在多线程实时系统中&#xff0c;一项工作的完成往往可以通过多个线程协调的方式共同来完成。 例如一项工作中的两个线程&#xff1a;一个线程从传感器中接收数据并且将数据写到共享内存中&#xff0c;同时另一个线程周期性地从共享内存中读取数据并发送出去显示&a…

SpringCloud系列篇:核心组件之网关组件

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringCloud的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.网关组件是什么 二. 网关组件的…

vivado 创建编译后工程

创建后期合成项目 合成后项目以合成网表、完全生成的块设计、完全生成的IP以及相应的约束。然后&#xff0c;您可以分析、布局和实施设计 注意&#xff1a;您可以使用XST或第三方合成工具来创建合成网表。 重要&#xff01;使用EDIF和NGC文件时&#xff0c;顶部单元格名称必…

java递归生成树型结构

java递归生成树 1.获取数据 public List<TreeClassifyRespVO> getTreeClassifyList(ClassifyPageReqVO reqVO) {List<ClassifyDO> classifyList classifyMapper.selectList(reqVO);List<TreeClassifyRespVO> childClassifyResp ClassifyConvert.INSTANCE…

MySQL之导入、导出

文章目录 1.navicat导入导出2.mysqldump命令导入导出2.1导出2.2导入 3.load data infile命令导入导出4.远程备份5.思维导图 1.navicat导入导出 使用Navicat工具导入t_log 共耗时 55s 2.mysqldump命令导入导出 2.1导出 导出表数据和表结构 语法&#xff1a; mysqldump -u用…

EasyExcel百万数据导入导出

文章目录 百万数据准备EasyExcel导出EasyExcel不支持并发写导出功能的代码片段 EasyExcel导入 https://gitee.com/antirust/idooy-stable/tree/master/idooy-EasyExcel 开发中&#xff0c;导入导出功能对于后台管理这样的系统来说太常用了&#xff0c;除了实现该功能外导入导出…

Python爬虫-爬取豆瓣Top250电影信息

&#x1f388; 博主&#xff1a;一只程序猿子 &#x1f388; 博客主页&#xff1a;一只程序猿子 博客主页 &#x1f388; 个人介绍&#xff1a;爱好(bushi)编程&#xff01; &#x1f388; 创作不易&#xff1a;喜欢的话麻烦您点个&#x1f44d;和⭐&#xff01; &#x1f388;…

QT qss文件设置样式

方式一 &#xff08;单个&#xff09; 方式二 &#xff08;全局&#xff09; 所有按钮都会采用这个样式。 方式三 &#xff08;qss文件&#xff09; 创建资源文件 创建qss文件&#xff08;Button.qss&#xff09; 引用qss文件 QApplication a(argc, argv);QString qss;QFile…

Kettle Local引擎使用记录(一)(基于Kettle web版数据集成开源工具data-integration源码)

Kettle Web &#x1f4da;第一章 前言&#x1f4da;第二章 demo源码&#x1f4d7;pom.xml引入Kettle引擎核心文件&#x1f4d7;java源码&#x1f4d5; controller&#x1f4d5; service&#x1f4d5; 其它&#x1f4d5; maven settings.xml &#x1f4d7;测试&#x1f4d5; 测试…

【STM32】STM32学习笔记-USART串口数据包(28)

00. 目录 文章目录 00. 目录01. 串口简介02. HEX数据包03. 文本数据包04. HEX数据包接收05. 文本数据包接收06. 预留07. 附录 01. 串口简介 串口通讯(Serial Communication)是一种设备间非常常用的串行通讯方式&#xff0c;因为它简单便捷&#xff0c;因此大部分电子设备都支持…

Python 使用input函数从键盘输入数据

在Python中&#xff0c;input()函数可以从键盘获取用户的输入数据。当我们使用input()函数时&#xff0c;会暂停程序的执行&#xff0c;等待用户输入数据&#xff0c;并将用户输入的数据作为字符串返回。 如&#xff1a; name input("请输入你的姓名&#xff1a;"…

Python私有变量的定义与访问

class Student():def __init__(self, name, age):self.name nameself.age ageself.__score 0def marking(self, score):if score < 0:return 分数不能为0self.__score scoreprint(self.name 同学本次得分是: str(self.__score)) def __talk(self): # 私有的类可通过在…

RocketMQ5-03RocketMQ-Dashboard和Java客户端访问示例

接上篇02快速部署RocketMQ5.x(手动和容器部署) 已经完成 RocketMQ5.0 环境的部署&#xff0c;就需要对这个环境进行测试&#xff0c;查看集群、写入消息、读取消息等 本篇教你如何使用和查看部署的服务&#xff1a; Docker部署 Dashboard 获取镜像并下载部署服务 客户端连接 …

哈希-力扣01两数之和

题目 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按任意顺…

spring boot 2升级为spring boot 3中数据库连接池druid的问题

目录 ConfigurationClassPostProcessor ConfigurationClassBeanDefinitionReader MybatisPlusAutoConfiguration ConditionEvaluator OnBeanCondition 总结 近期给了一个任务&#xff0c;要求是对现有的 spring boot 2.x 项目进行升级&#xff0c;由于 spring boot 2.x 版…

Linux Capabilities 进阶实战

目录 1. 快速回顾 2. 为可执行文件分配 capabilities 3. 构建半特权环境 4. 容器与 capabilities Linux Capabilities 基础概念与基本使用 上一篇学习了LinuxCapabilities的基础知识和基本使用&#xff0c;因为后面需要学习Docker的逃逸&#xff0c;理解Linux Capabilitie…