二叉树堆的应用实例分析:堆排序 | TOP-K问题


在这里插入图片描述

📷 江池俊: 个人主页
🔥个人专栏: ✅数据结构冒险记 ✅C语言进阶之路
🌅 有航道的人,再渺小也不会迷途。


在这里插入图片描述

文章目录

    • 前言
    • 一、堆排序
      • 1.1 排序思想
      • 1.2 堆排序过程(图解)
      • 1.3 堆排序代码(升序为例)
    • 二、TOP-K问题
      • 2.1 TOP-K问题思路
      • 2.2 随机生成随机数并存入文件
      • 2.3 建小堆取前 k 个最大的数

前言

在学习堆排序和TOP-K问题之前,大家需要先熟悉两个算法(即 向上调整向下调整 算法),这两大算法可谓是它们的核心。话不多说,我们直接上手。

一、堆排序

注意:当要求排序为升序,在建堆时需要建成大堆,反过来当要求降序,在建堆时就需要建成小堆。


1.1 排序思想

堆排序是一种有效的排序算法,它的 核心思想将一个无序数组构建成一个大顶堆(或小顶堆),然后将堆顶元素(最大值或最小值)与堆尾元素互换,之后将剩余的元素重新调整为大顶堆(或小顶堆),以此类推,直到整个数组有序。

  • 当要求排序为升序时,我们希望输出的结果是 从小到大。为了满足这个需求,在建堆时需要将较大的元素放在堆顶,这样在每次交换后,最大的元素会被放在数组的最后面。因此,在建堆过程中需要将数组建成大顶堆。
  • 相反,当要求排序为降序时,我们希望输出的结果是 从大到小。为了满足这个需求,在建堆时需要将较小的元素放在堆顶,这样在每次交换后,最小的元素会被放在数组的最后面。因此,在建堆过程中需要将数组建成小顶堆。

这里我们以升序为例,如图:

在这里插入图片描述


1.2 堆排序过程(图解)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3 堆排序代码(升序为例)

typedef int HPDataTypevoid Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}//向上调整
void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;//while (parent >= 0)while (child > 0){if (a[child] > a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;//child = (child - 1) / 2;//parent = (parent - 1) / 2;}else{break;}}
}// 向下调整
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[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}//堆排序 --- 升序
void HeapSort(int* a, int n)
{//建大堆//向上调整建对堆0(N*logN)/*for (int i = 1; i < n; i++){AdjustUp(a, i);}*///向下调整建堆// (找倒数第一个非叶子节点,从该节点位置开始往前一直到根节点,遇到一个节点,应用向下调整)0(N)for (int 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;}}

在这里插入图片描述



二、TOP-K问题

TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。


2.1 TOP-K问题思路

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

  1. 用数据集合中前K个元素来建堆
    • 前k个最大的元素,则建小堆
    • 前k个最小的元素,则建大堆
  2. 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
    • 将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

2.2 随机生成随机数并存入文件

//产生一千万个随机数
void CreateNDate()
{// 造数据int n = 10000000;srand(time(0)); //srand()最多产生三万多个随机数const char* file = "data.txt";FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");return;}for (size_t i = 0; i < n; ++i){int x = (rand() + i) % 10000000; //+i减少随机数的重复fprintf(fin, "%d\n", x);}fclose(fin);
}

【运行结果】:
生成 0~9999999 的随机数
在这里插入图片描述

2.3 建小堆取前 k 个最大的数

将 “data.txt” 文件中的数据依次读取建小堆,最后堆中的数据就是文件中最大的前 k 个数。

//向上调整 --- 小堆
void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;//while (parent >= 0)while (child > 0){if (a[child] < a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;//child = (child - 1) / 2;//parent = (parent - 1) / 2;}else{break;}}
}// 向下调整
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[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}// 取前k个最大的数
void PrintTopK(const char* file,int k)
{FILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen error");return;}//建一个k个数的小堆int* minheap = (int*)malloc(sizeof(int) * k);if (minheap == NULL){perror("malloc error");return;}//读取前k个,建小堆for (int i = 0; i < k; i++){fscanf(fout, "%d", &minheap[i]);AdjustUp(minheap, i);}//读取所有数据,建成小堆,最大的前k个数据就在堆中int x = 0;while (fscanf(fout, "%d", &x) != EOF){if (x > minheap[0]){minheap[0] = x;AdjustDown(minheap, k, 0);}}for (int i = 0; i < k; i++){printf("%d ", minheap[i]);}printf("\n");free(minheap);fclose(fout);
}

运行结果:

在这里插入图片描述
【打开文件修改数据,测试程序正确性】:
在这里插入图片描述
在这里插入图片描述

修改数据后的运行结果:

在这里插入图片描述


🔥💖以上TOP-K问题只是取前k个最大数据的例子,取前k个最小数据与此类似,这里博主就不再赘述,希望这篇文章能够帮到大家,期待大家的三连支持🤞

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

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

相关文章

IP数据云:实战网络安全的得力利器

在当今数字化时代&#xff0c;企业和个人面临着日益复杂和频繁的网络安全威胁。为了应对这些挑战&#xff0c;IP数据云作为一项全面的网络安全解决方案&#xff0c;已经在多个实际案例中展现了其卓越的能力。 1、识别并隔离异常行为 挑战&#xff1a;一家大型金融机构发现其内…

Github 不能访问,提示:port 22: Connection timed out

问题描述 github clone 代码出现错误&#xff1a; $ git clone gitgithub.com:Atlan4/Fnirsi1013D.git Cloning into Fnirsi1013D... ssh: connect to host github.com port 22: Connection timed out fatal: Could not read from remote repository.Please make sure you ha…

Unity 外观模式(实例详解)

文章目录 示例1&#xff1a;初始化游戏场景中的多个子系统示例2&#xff1a;管理音频播放示例3&#xff1a;场景加载流程示例4&#xff1a;UI管理器示例5&#xff1a;网络服务通信 在Unity中使用外观模式&#xff08;Facade&#xff09;时&#xff0c;主要目的是为了简化复杂子…

Webpack5 基本使用 - 1

Webpack 是什么 webpack 的核心目的是打包&#xff0c;即把源代码一个一个的 js 文件&#xff0c;打包汇总为一个总文件 bundle.js。 基本配置包括mode指定打包模式&#xff0c;entry指定打包入口&#xff0c;output指定打包输出目录。 另外&#xff0c;由于 webpack默认只能打…

6轴机器人运动正解-逆解控制【1】——三种控制位姿的方式

概览&#xff1a; 通过运动学正解控制机器人运动通过运动学逆解控制机器人运动一个简单的物体搬运&#xff08;沿轨迹运动&#xff09; 后续会陆续更新&#xff08;本例仅供学习交流用&#xff09; 一、6轴机器人 二、运动正解控制 通过修改各个轴的角度&#xff0c;实现末…

宠物互联网医院系统:数字化呵护你爱宠的新时代

宠物互联网医院系统正在为宠物主人提供一种前所未有的数字化健康护理体验。通过结合创新技术&#xff0c;这一系统旨在让宠物医疗变得更加便捷、智能和个性化。让我们深入探讨宠物互联网医院系统的技术核心&#xff0c;以及如何应用代码为你的爱宠提供最佳关怀。 1. 远程医疗…

linux clickhouse 安装

1、官网下载clickhouse安装包 下载地址&#xff0c; clickhouse分lts和stable版本&#xff0c;lts是长期版本&#xff0c;一般选择安装lts版本。 其中clickhouse-server是clickhouse服务&#xff0c;就是用来访问数据存储数据&#xff0c;clickhouse-client是用来通过命令访问数…

Java中的HTTPS通信

在Java中实现HTTPS通信&#xff0c;主要涉及到SSL/TLS协议的使用&#xff0c;用于提供数据传输的安全性。下面我们将深入探讨如何使用Java进行HTTPS通信。 一、基本概念 HTTPS&#xff0c;全称为Hypertext Transfer Protocol Secure&#xff0c;是HTTP的安全版本。它使用SSL/…

CSS之高度塌陷和外边距塌陷

目录 1.高度塌陷&#xff08;原因&#xff0c;如何解决&#xff09; 【概念介绍】 【解决办法】 【概念介绍-BFC】 【拓展-BFC的触发条件】 2.外边距塌陷 &#xff08;原因&#xff0c;如何解决&#xff09; 【概念介绍】 【两种情况】 1.相邻块元素 2.嵌套块元素 【…

码龙乘风 - AI助你不断升级的编程体验

这几年,人工智能(AI)技术飞速发展,现已深入到编程工具之中,助力程序员不断提高工作效率。下面我就谈谈 AI 给编程带来的一些实用功能,以及如何利用好这些功能,让编码变得更轻松、高效。 一、AI辅助编写代码 现在已有不少编程工具加入了AI助手,可以在编码时自动补全代码、提示…

中移(苏州)软件技术有限公司面试问题与解答(4)—— virtio所创建的设备1

接前一篇文章&#xff1a;中移&#xff08;苏州&#xff09;软件技术有限公司面试问题与解答&#xff08;0&#xff09;—— 面试感悟与问题记录 本文参考以下文章&#xff1a; VirtIO实现原理——PCI基础 VirtIO实现原理——virtblk设备初始化 特此致谢&#xff01; 本文对…

eNSP学习——VLAN基础配置及Access接口

目录 原理概述 实验内容&#xff1a; 实验目的&#xff1a; 实验步骤&#xff1a; 实验拓扑 配置过程 实验编址 基本配置 创建vlan 配置Access接口 原理概述 早期的局域网技术是基于总线型结构的。总线型拓扑结构是由一根单电缆连接所有主机&#xff0c;就导致所…

微认证 openEuler社区开源贡献实践

文章目录 1. 开源与开源社区2. openEuler 社区概述3.参与openEuler社区贡献4.openEuler软件包开发Linux软件管理——源码编译 1. 开源与开源社区 Richard Matthew Stallman&#xff0c;1983年9月推出GNU项目&#xff0c;并发起自由软件运动(free software movement或free/open…

《Linux高性能服务器编程》笔记07

Linux高性能服务器编程 本文是读书笔记&#xff0c;如有侵权&#xff0c;请联系删除。 参考 Linux高性能服务器编程源码: https://github.com/raichen/LinuxServerCodes 豆瓣: Linux高性能服务器编程 文章目录 Linux高性能服务器编程第14章 多线程编程14.1 Linux线程概述14…

7.FPR/TNR-机器学习模型性能的常用的评估指标

FPR/TNR指标在机器学习中并不常用&#xff0c;因此&#xff0c;此处简单的介绍相应的概念和公式&#xff0c;帮助大家全面了解机器学习相关的评估指标。 一.FPR/TNR的定义和公式 在机器学习中&#xff0c;性能评估是了解模型在处理任务中的效果的关键部分。FPR&#xff08;Fa…

内网穿透、远程桌面、VPN的理解

最近在研究内网穿透的相关技术&#xff0c;然后回想起一些相关的技术&#xff0c;比如说要远程桌面公司的电脑&#xff0c;VPN连入内网等。然后想着在此处记录一下&#xff0c;各个的区别&#xff0c;这个纯粹是从技术层面的理解&#xff0c;此处不详细解释怎么去实现或者用什么…

el-table在鼠标移动到单元格时变为下拉框,否则是普通文本

el-table将多个单元格改为下拉框&#xff0c;导致渲染卡顿&#xff0c;解决方法在鼠标移动到单元格时变为下拉框&#xff0c;否则是普通文本 <el-table-column label"显示方向" width"150px" align"center" key"direction" prop&q…

Jmeter分布式压测过程常见问题

1、JMeter分布式压测试&#xff0c;结果树响应数据为空 解决&#xff1a;打开主控机的jmeter-bin,打开jmeter-properties,将modeStandard 前面的#去掉&#xff0c;保存重启jmeter 2、JMeter压力测试报Address already in use: connect错误 方法一&#xff1a; cmd中&#x…

SpringBoot实现热部署

一、热部署&#xff08;Hot Swap&#xff09; 从Java1.4起&#xff0c;JVM引入了HotSwap&#xff0c;能够在Debug的时候更新类的字节码。所以使用热部署&#xff0c;可以实现修改代码后&#xff0c;无须重启服务就可以加载修改的代码&#xff0c;但是它只能用来更新方法体。 实…

2023-2024年重庆职业院校技能大赛“信息安全管理与评估”比赛样题

2023 年重庆职业院校技能大赛&#xff08;高等职业教育&#xff09; “信息安全管理与评估”样题任务书 第一阶段&#xff1a;任务 1 网络平台搭建&#xff08;50 分&#xff09;任务 2 网络安全设备配置与防护&#xff08;250 分&#xff09; 第二阶段&#xff1a;第一部分 网…