堆与堆排序及 Top-K 问题解析:从原理到实践

article/2025/6/16 13:34:10

一、堆的本质与核心特性

堆是一种基于完全二叉树的数据结构,其核心特性为父节点与子节点的数值关系,分为大堆和小堆两类:

 

  • 大堆:每个父节点的值均大于或等于其子节点的值,堆顶元素为最大值。如:

  • 小堆:每个父节点的值均小于或等于其子节点的值,堆顶元素为最小值。

这种特性使得堆能够高效地支持插入删除堆顶元素获取极值等操作,时间复杂度均为 \(O(\log n)\),其中 n 为堆中元素个数。

二、堆排序:基于堆的经典排序算法

(一)算法思想

堆排序的核心是利用堆的特性实现排序,分为两个阶段:

  1. 建堆阶段:将初始序列构建成一个大堆(或小堆)。
  2. 排序阶段:依次将堆顶元素与末尾元素交换,调整剩余元素维持堆结构,直至排序完成。

(二)实现步骤(以小堆为例)

假设现有数组 data = { 4,2,8,1,5,6,9,7,2,7,9},如图

其排序过程如下:

  1. 构建小堆
    • 从最后一个非叶子节点(索引为(n-1-1) / 2)开始调整。
    • 运用向下调整算法进行处理。
//向下调整
void AdjustDown(HPDataType* a, int n, int parent)
{int child = parent * 2 + 1;while(child < n)//找不到孩子{//找出小的孩子if(child + 1 < n && a[child + 1] < a[child]){child = child + 1;}//调整if(a[child] < a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

 

  1. 排序过程
    • 交换堆顶与末尾元素,此时末尾元素为最小值,固定。
    • 对前 n - 1 个元素重新调整为小堆。
    • 重复交换和调整操作,最终得到有序数组 {9 9 8 7 7 6 5 4 2 2 1}。

 

(三)代码实现(C)

//堆排序(O(N*logN))
void HeapSort(int* a, int n)
{//降序,建小堆//升序,建大堆// for(int i = 1; i < n; i++)// {//     AdjustUp(a, i);//向上调整建堆(O(N*logN))// }for(int i = (n-1-1)/2; i >= 0; i--){AdjustDown(a, n, i);//向下调整建堆(O(N))}int end = n - 1;//(O(N*logN))while(end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}for(size_t i = 0; i < n; i++){printf("%d ",a[i]);}printf("\n");
}

三、Top-K 问题:基于堆的高效求解方案

(一)问题定义

在海量数据中快速找到最大的 K 个数(或最小的 K 个数),例如从 100 万个数中找出前 10 大的数。

(二)核心思路

  • 求最大的 K 个数:使用小堆,堆中维护当前最大的 K 个数。遍历数据时,若当前数大于堆顶(堆中最小值),则替换堆顶并调整堆。
  • 求最小的 K 个数:使用大堆,堆中维护当前最小的 K 个数。遍历数据时,若当前数小于堆顶(堆中最大值),则替换堆顶并调整堆。

(三)代码实现(C,求最大的 K 个数)

假设文件 data.txt 中存储了大量整数,可通过以下步骤进行Top-K 求解:

  1. 输入数据:将数据输入进data.txt中
  2. Top-K 查询:调用 topK 函数获取前 K 大或前 K 小的元素。
void CreateNData()
{//造数据int n = 100000;srand((unsigned int)time(NULL));const char* file = "data.txt";FILE* fin = fopen(file, "w");if(fin == NULL){perror("fopen fail!");return;}for(int i = 0; i < n; i++){int x = (rand()+i) % 1000000;fprintf(fin, "%d\n", x);}fclose(fin);
}void Test03()
{/* A *///读前k个数据system("chcp 65001");int k = 0;printf("请输出k>:");scanf("%d",&k);int* kminheap = (int*)malloc(k*sizeof(int));if(kminheap == NULL){perror("malloc fail!");return;}const char* file = "data.txt";FILE* fout = fopen(file, "r");if(fout == NULL){perror("fopen fail!");exit(1);}for(int i = 0; i < k; i++){fscanf(fout, "%d", &kminheap[i]);}//建小堆for(int i = (k-1-1)/2; i >= 0; i--){AdjustDown(kminheap, k, i);}//读取剩下N-K个数int x = 0;while(fscanf(fout, "%d", &x) > 0){if(x > kminheap[0]){kminheap[0] = x;AdjustDown(kminheap, k, 0);}}//打印topkprintf("最大前%d个数",k);for(int i = 0; i < k; i++){printf("%d ", kminheap[i]);}printf("\n");
}

四、性能分析与应用场景

(一)时间复杂度

  • 堆排序:建堆时间为 ,每次调整时间为 (O(log n)),总时间复杂度为 (O(nlog n)),属于不稳定排序。
  • Top-K 问题:遍历数据时间为 (O(n)),每次堆操作时间为 (O(\log K)),总时间复杂度为 (O(nlog K)),适用于 (K 远小于 n) 的场景。

(二)应用场景

  • 堆排序:适用于内存中数据排序,尤其适合不需要额外空间的原地排序(空间复杂度 (O(1)))。
  • Top-K 问题
    • 海量日志分析:提取热门访问记录。
    • 数据挖掘:找出频繁出现的元素。
    • 实时系统:实时监控数据中的极值点。

五、总结

堆作为一种高效的数据结构,通过巧妙的完全二叉树性质实现了快速的极值操作。堆排序和 Top-K 问题是其典型应用,前者利用建堆和交换实现排序,后者通过维护固定大小的堆解决海量数据中的极值查询。理解堆的核心原理与应用,能有效提升数据处理的效率,尤其在面对大规模数据时优势显著。

 


http://www.hkcw.cn/article/BpsTMgDOVv.shtml

相关文章

【题解-洛谷】P8094 [USACO22JAN] Cow Frisbee S

题目&#xff1a;P8094 [USACO22JAN] Cow Frisbee S 题目描述 Farmer John 的 N ( N ≤ 3 10 5 ) N\ (N\le 3\times 10^5) N (N≤3105) 头奶牛的高度为 1 , 2 , … , N 1, 2, \ldots, N 1,2,…,N。一天&#xff0c;奶牛以某个顺序排成一行玩飞盘&#xff1b;令 h 1 … h …

如何利用差分隐私技术在医疗领域守护患者隐私

在数字化医疗快速发展的当下&#xff0c;医疗数据已然成为一座蕴藏无限价值的宝库。一份完整的电子病历&#xff0c;不仅记录着患者的疾病诊断、治疗记录&#xff0c;还可能包含基因数据、生活习惯等敏感信息&#xff1b;而基因检测报告中携带的遗传密码&#xff0c;更是与个人…

Kanass入门教程- 事项管理

kanass是一款国产开源免费、简洁易用的项目管理工具&#xff0c;包含项目管理、项目集管理、事项管理、版本管理、迭代管理、计划管理等相关模块。工具功能完善&#xff0c;用户界面友好&#xff0c;操作流畅。本文主要介绍事项管理使用指南。 1、添加事项 事项有多种类型 分…

主人回应狗王“长毛”爆火 小狗成网红引来百万关注

近日,河北承德一只下司犬“长毛”的视频在外网爆火。视频中,“长毛”凭借威严的姿态让闹事的狗狗臣服。因此小狗被外国网友取名“查理国王”“狗王”等称号,连小狗的肖像都被印在T恤上作为周边售卖。火爆全网的狗王“长毛”。网络截图网友们纷纷表达了自己的惊叹与崇拜:“阿…

描述性统计的可视化分析

初步研究数据的分布时&#xff0c;最直观的方法就是可视化分析了。 1. 直方图 直方图&#xff08;histogram&#xff09;出现得很早&#xff0c;而且应用广泛。 直方图是以一种图形方法来概括给定数值X的分布情况的图示。 如果X是离散的变量&#xff0c;比如股票类型&#xf…

梅花鹿横穿马路被车撞倒后跑进丛林 后视镜遭殃引发热议

5月31日清晨,大连市民在滨海路晨跑时目睹了一起意外。一只梅花鹿试图穿过马路时被一辆小车撞翻在地,但随后它站起身来,迅速跑进了路边的树林。这辆小车的左侧后视镜被撞断。网友拍摄的视频显示,这只梅花鹿从绿化带突然跑向机动车道,一辆白色汽车避让不及撞了上去。此事引起…

福建8岁男童失踪近一个月 搜寻仍在继续

8岁男童邹某樽在福建仙游县石谷解登山时与家人失联,至今已失踪近一个月。网友们纷纷呼唤他快回家过“六一”儿童节。5月4日,邹某樽随父母到石谷解登山,在下山过程中与父母失去联系。当天16时左右,孩子母亲报警后,仙游县立即启动应急响应机制,组织公安、森林消防、救援队、…

论文笔记: Urban Region Embedding via Multi-View Contrastive Prediction

AAAI 2024 1 INTRO 之前基于多视图的region embedding工作大多遵循相同的模式 单独的单视图表示多视图融合 但这种方法存在明显的局限性&#xff1a;忽略了不同视图之间的信息一致性 一个区域的多个视图所携带的信息是高度相关的&#xff0c;因此它们的表示应该是一致的如果能…

Python实现P-PSO优化算法优化卷积神经网络CNN分类模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 随着人工智能技术的快速发展&#xff0c;卷积神经网络&#xff08;CNN&#xff09;在图像分类、目标检测和模式识别…

3D-激光SLAM笔记

目录 定位方案 编译tbb ros2humble安装 命令 colcon commond not found 栅格地图生成&#xff1a; evo画轨迹曲线 安装gtsam4.0.2 安装ceres-solver1.14.0 定位方案 1 方案一&#xff1a;改动最多 fasterlio 建图&#xff0c;加闭环优化&#xff0c;参考fast-lio增加关…

VizCut:全免费无广告的批量视频去重剪辑工具,支持无水印下载与GPU加速

软件介绍 VizCut 是一款优秀的本地批量自动剪辑工具&#xff0c;可制作和分享剪辑模板&#xff0c;已提供20种剪辑方案&#xff0c;内置众多扫光蒙版素材。支持二次去重批量处理&#xff0c;完全免费&#xff0c;无广告&#xff0c;且支持视频无水印解析下载&#xff0c;非常强…

使用Gemini, LangChain, Gradio打造一个书籍推荐系统 (第四部分)

第四部分&#xff1a;为每本书加上情绪标签 import pandas as pd books pd.read_csv("books_with_categories.csv") from transformers import pipeline classifier pipeline("text-classification",model"j-hartmann/emotion-english-distilrober…

JS逆向案例—喜马拉雅xm-sign详情页爬取

JS逆向案例——喜马拉雅xm-sign详情页爬取 声明网站流程分析总结 声明 本文章中所有内容仅供学习交流&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&am…

Java日志体系

前言&#xff1a;&#x1f42d;&#x1f42d;已经两年没更新了&#xff0c;主要原因是因为&#x1f42d;&#x1f42d;考研去了&#xff0c;前段时间读研和工作压力都比较大所以没时间更新&#xff0c;今后&#x1f42d;&#x1f42d;会慢慢恢复更新 1 流程和原理梳理 日志体…

【HW系列】—Windows日志与Linux日志分析

文章目录 一、Windows日志1. Windows事件日志2. 核心日志类型3. 事件日志分析实战详细分析步骤 二、Linux日志1. 常见日志文件2. 关键日志解析3. 登录爆破检测方法日志分析核心要点 一、Windows日志 1. Windows事件日志 介绍&#xff1a;记录系统、应用程序及安全事件&#x…

使用交叉编译工具提示stubs-32.h:7:11: fatal error: gnu/stubs-soft.h: 没有那个文件或目录的解决办法

0 前言 使用ST官方SDK提供的交叉编译工具、cmake生成Makefile&#xff0c;使用make命令生成可执行文件提示fatal error: gnu/stubs-soft.h: 没有那个文件或目录的解决办法&#xff0c;如下所示&#xff1a; 根据这一错误提示&#xff0c;按照网上的解决方案逐一尝试均以失败告…

苏超第三轮徐州2-1战胜连云港 端午假期迎首胜

北京时间5月31日,2025年江苏省城市足球联赛第3轮,徐州队主场以2-1战胜连云港队,迎来首胜。这场比赛正值端午假期,吸引了22198位球迷涌入徐州奥体中心观赛,上座人数甚至超过了部分中超比赛。目前,徐州队在先赛一场的情况下取得1胜2平积5分的成绩,暂时排名积分榜第三。而连…

富翁错失NASA局长提名 白宫:必须完全认同特朗普

亿万富翁错失NASA局长提名 白宫:必须完全认同特朗普当地时间5月31日,白宫表示,特朗普将很快宣布新的NASA局长提名人选。△贾里德艾萨克曼(资料图)白宫尚未解释原提名人贾里德艾萨克曼(Jared Isaacman)为何退出。据知情人士称,白宫已决定撤回艾萨克曼的提名。白宫发言人…

[USACO1.5] 八皇后 Checker Challenge Java

import java.util.*;public class Main {// 标记 对角线1&#xff0c;对角线2&#xff0c;所在x轴 是否存在棋子static boolean[] d1 new boolean[100], d2 new boolean[100], d new boolean[100]; static int n, ans 0;static int[] arr new int[14]; // 记录一轮棋子位置…

数据库核心技术深度剖析:事务、索引、锁与SQL优化实战指南(第四节)----从行级锁到死锁处理的系统梳理

Introduction&#xff1a;收纳技术相关的数据库知识 事务、索引、锁、SQL优化 等总结&#xff01; 文章目录 数据库锁行级锁(Row-Level)属性锁共享锁(Shared Locks)排它锁(Exclusive Locks) 锁实现方式Record Lock(记录锁)Gap Lock(间隙锁)Next-Key Lock(临键锁) 加锁机制乐观锁…