堆的实现以及应用
💓博主个人主页:不是笨小孩👀
⏩专栏分类:数据结构与算法👀 刷题专栏👀 C语言👀
🚚代码仓库:笨小孩的代码库👀
⏩社区:不是笨小孩👀
🌹欢迎大家三连关注,一起学习,一起进步!!💓
堆
- 堆的实现
- 堆的结构
- 堆的接口及实现
- 堆的插入
- 堆的删除
- 其他接口
- 堆的应用
- 堆排序
- 向上调整法建堆
- 向下调整法建堆
- TopK问题
堆的实现
我们说堆在物理上是一个数组,逻辑上它是一个完全二叉树,我们可以通过它的下标来计算父亲和孩子之间的关系。
> 左孩子=父亲×2+1;
右孩子=父亲×2+2;
父亲=(孩子-1)/2;
堆的结构
堆的结构和顺序表是一样的。
typedef int HPDateType;typedef struct Heap
{HPDateType* a;int size;int capacity;
}HP;
堆的接口及实现
堆的接口有哪些呢?
//初始化
void HeapInit(HP* php); //销毁
void HeapDestroy(HP* php);//插入
void HeapPush(HP* php, HPDateType x);//删除
void HeapPop(HP* php);//取对顶的数据
HPDateType HeapTop(HP* hp);// 堆的数据个数
int HeapSize(HP* hp);// 堆的判空
int HeapEmpty(HP* hp);
我们主要讲一下删除和插入,其他的非常简单。
堆的插入
假设先插入一个10到数组的尾上,再进行向上调整算法,直到满足堆。
代码如下:
void HeapPush(HP* php, HPDateType x)
{assert(php);if (php->capacity == php->size){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDateType* pa = (HPDateType*)realloc(php->a, sizeof(HPDateType) * newcapacity);if (pa == NULL){perror("realloc fail");exit(-1);}php->a = pa;php->capacity = newcapacity;}php->a[php->size] = x;php->size++;//向上调整算法AdjustUp(php->a, php->size-1);
}
不知道向上调整算法的,请戳。
堆的删除
删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法,使数组满足堆的性质。
代码如下:
//删除
void HeapPop(HP* php)
{assert(php);assert(php->size);//交换Swap(&php->a[0], &php->a[php->size - 1]);//删除数据php->size--;//向下调整算法AdjustDown(php->a, php->size, 0);}
不懂向下调整算法请戳。
其他接口
其他接口和顺序表差不多,这里给大家看一下代码。
//初始化
void HeapInit(HP* php)
{assert(php);php->a = NULL;php->capacity = 0;php->size = 0;
}//取对顶的数据
HPDateType HeapTop(HP* php)
{assert(php);assert(php->size);return php->a[0];
}// 堆的数据个数
int HeapSize(HP* php)
{assert(php);return php->size;
}// 堆的判空
int HeapEmpty(HP* php)
{assert(php);return php->size == 0;
}//销毁
void HeapDestroy(HP* php)
{assert(php);free(php->a);php->a = NULL;php->size = php->capacity = 0;}
那么堆的实现就是这么多的内容,重点是向上调整,向下调整算法,而向下调整算法是最最最重要的。
堆的应用
堆排序
我们先思考一个问题,排升序的话建大堆还是建小堆
答案是建大堆,有人就会有疑惑了,为什么要建大堆,问什么不建小堆呢,如果建小堆的话,那么堆顶的元素就是最小的,由于要排升序,我们就需要跳过第一个元素,但是后面的元素的父子关系就全乱了,需要重新建堆,而重新建堆的代价是非常大了,所以我们要建大堆,然后和删除一样,这时堆顶的元素是最大的,我们将堆顶的元素和最后一个元素换一下,然后使用向下调整算法,只不过需要将有效数据的个数减少一个就可以了。
排升序建大堆,那么排降序就是建小堆。
有人会说我们实现了堆,我们可以把数组的元素依次插入堆,然后依次按上面的操作,就可以实现排序了,最后再把数据拷回来就可以了。但是我们一般不这样玩,因为那样插入需要空间复杂度,而且把数据拷回来也是很挫的操作,我们一般都是在原数组之间建堆,我们可以用向上调整法建堆,也可以用向下调整法建堆。
向上调整法建堆
把数据都分割开,看出依次插入的,因为第一个数据就一个数据本身就是一个堆,所以直接从第二个数据开始就可以。
for (int i = 1; i < sz; i++)
{//这就和我们上面画的图想对应,依次插入,并且保证前面是堆//向上调整传的是数组和孩子节点(也就是需要调整的节点)AdjustUp(arr, i);
}
向下调整法建堆
向下调整的前提是两个孩子都是堆,所以我们可以从后往前调,而叶子节点不需要调,所以我们从最后一片叶子的父亲开始就可以。
for(int i = (sz - 1 - 1) / 2; i >= 0; i--)
{//sz是数组的大小//向下调整传的是数组,数组的大小,以及需要调的父亲节点AdjustDown(arr, sz, i);
}
我们搞清楚这个以后就可以开始我们的堆排序了。
1.我们需要建堆。
2.我们需要交换堆顶和最后一个元素的数据,然后进行向下调整算法。
由于我们建堆和调整数据都需要向下调整算法,所以我们掌握了向下调整算法就可以完成堆排序。
代码如下:
//交换函数
void Swap(int* p1, int* p2)
{int tmp = 0;tmp = *p1;*p1 = *p2;*p2 = tmp;
}//向上调整算法
void AdjustUp(int* arr, int child)
{int parent = (child - 1) / 2;while (child > 0){if (arr[child] > arr[parent]){Swap(arr + child, arr + parent);child = parent;parent = (child - 1) / 2;}else{break;}}
}
//向下调整算法
void AdjustDown(int* arr, int sz, int parent)
{//假设是左孩子int child = 2 * parent + 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 HeapSort(int* arr, int sz)
{//假设排升序,建大堆//向上调整算法建堆/*for (int i = 1; i < sz; i++){AdjustUp(arr, i);}*///向下调整算法建堆for(int i = (sz - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr, sz, i);}//交换收尾,接着向下调整算法int end = sz - 1;while (end > 0){//交换首尾Swap(&arr[0], &arr[end]);//向下调整AdjustDown(arr, end, 0);end--;}
}
堆排序就讲到这里,有什么不理解的可以私信博主。
TopK问题
TopK是什么?
求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。
那这怎么解决呢?和堆又有什么关系呢?
对于Top-K问题,能想到的最简单直接的方式就是排序,但是:如果数据量非常大,排序就不太可取了(可能
数据都不能一下子全部加载到内存中)。最佳的方式就是用堆来解决,基本思路如下:
- 用数据集合中前K个元素来建堆
前k个最大的元素,则建小堆
前k个最小的元素,则建大堆- 用剩余的N-K个元素依次与堆顶元素来比较,不满足则替换堆顶元素
我这里用数组来给大家实现一下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = 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[parent] > arr[child]){Swap(&arr[parent], &arr[child]);parent = child;child = parent * 2 + 1;}else{break;}}
}
void PrintTopK(int* a, int n, int k)
{//直接在原数组的前K个建小堆for (int i = (k - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, k, i);}int top = 0;for (int i = k; i < n; i++){top = a[i];//取后k个元素依次和堆顶的元素比较,大的就替换,然后向下调整if(a[0] < top){a[0] = top;AdjustDown(a, k, 0);}}for (int i = 0; i < k; i++){printf("%d ", a[i]);}
}
void TestTopk()
{int n = 10000;int* a = (int*)malloc(sizeof(int) * n);srand((size_t)time(NULL));//生成一万个随机数for (int i = 0; i < n; ++i){a[i] = rand() % 1000000;}a[5] = 1000000 + 1;a[1231] = 1000000 + 2;a[531] = 1000000 + 3;a[5121] = 1000000 + 4;a[115] = 1000000 + 5;a[2335] = 1000000 + 6;a[9999] = 1000000 + 7;a[76] = 1000000 + 8;a[423] = 1000000 + 9;a[3144] = 1000000 + 10;PrintTopK(a, n, 10);free(a);
}int main()
{TestTopk();return 0;
}
那么堆讲到这里就结束了,今天的分享到这里也结束了,感谢大家的关注和支持。
相关文章:

堆的实现以及应用
💓博主个人主页:不是笨小孩👀 ⏩专栏分类:数据结构与算法👀 刷题专栏👀 C语言👀 🚚代码仓库:笨小孩的代码库👀 ⏩社区:不是笨小孩👀 🌹欢迎大家三连关注&…...

MySql011——检索数据:过滤数据(使用正则表达式)
前提:使用《MySql006——检索数据:基础select语句》中创建的products表 一、正则表达式介绍 关于正则表达式的介绍大家可以看我的这一篇博客《Java038——正则表达式》,这里就不再累赘。 二、使用MySQL正则表达式 2.1、基本字符匹配 检索…...

数据结构与算法-栈(LIFO)(经典面试题)
一:面试经典 1. 如何设计一个括号匹配的功能?比如给你一串括号让你判断是否符合我们的括号原则, 栈 力扣 2. 如何设计一个浏览器的前进和后退功能? 思想:两个栈,一个栈存放前进栈&…...

NSI45030AT1G LED驱动器方案为汽车外部及内部照明恒流稳流器(CCR)方案
关于线性恒流调节器(CCR):是一种用于控制电流的稳定输出。它通常由一个功率晶体管和一个参考电流源组成。CCR的工作原理是通过不断调节功率晶体管的导通时间来维持输出电流的恒定。当输出电流超过设定值时,CCR会减少功率晶体管的导…...

uni-app中使用pinia
目录 Pinia 是什么? uni-app 使用Pinia main.js 中引用pinia 创建和注册模块 定义pinia方式 选项options方式 定义pinia 页面中使用 pinia选项options方式 函数方式 定义pinia 页面中使用 函数方式 定义的pinia Pinia 是什么? Pinia࿰…...

Spring之事务管理
文章目录 前言一、事务及其参数含义1.事务的四个特性2.事务的传播行为(propagation)3.事务隔离性4.事务的隔离级别(ioslation)5.timeout(超时)6.readOnly(是否只读)7.rollbackFor&am…...
linux常见的mysql问题
当涉及到MySQL在Linux系统上的常见问题时,以下是10个经常遇到的问题及其解答: 无法连接到MySQL服务器。 确保MySQL服务器正在运行:可以使用systemctl status mysql或service mysql status命令检查MySQL服务状态。确保MySQL服务器网络设置正确…...

常见分辨率时序信息
分辨率列表 分辨率一:640x480(逐行) 分辨率二:800x600(逐行) 分辨率三:1024x768(逐行) 分辨率四:大名鼎鼎720P(逐行) 注:选择720P@30帧的,需拉长HOR TOTAL TIME 分辨率五:1280x800(逐行) 分辨率六:1280x960(逐行...

机器人CPP编程基础-05完结The End
非常不可思议……之前四篇博文竟然有超过100的阅读量…… 此文此部分终结,没有继续写下去的必要了。 插入一个分享: 编程基础不重要了,只要明确需求,借助AI工具就能完成一个项目。 当然也不是一次成功,工具使用也需要…...
数据库应用系统DBAS功能设计与实施(三级数据库)
目录 一、了解软件体系结构及设计过程 1、软件体系结构与设计过程 2、软件设计过程 二、了解DBAS总体设计 1、DBAS体系结构设计 2、软件体系结构设计 3、软硬件选型与配置设计 4、业务规则初步设计 三、了解DBAS功能概要设计 1、表示层概要设计 2、业务逻辑层概要设计…...
快速幂典型
题目描述 求 a 乘 b 对 p 取模的值,其中 1≤a,b,p≤1018。 输入描述: 第一行a,第二行b,第三行p。 输出描述: 一个整数,表示abmodp的值。 示例1 输入 2 3 9 输出 6 #include<bits/stdc.h> using namespace std; t…...

计算机竞赛 python+opencv+机器学习车牌识别
0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 基于机器学习的车牌识别系统 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:4分工作量:4分创新点:3分 该项目较为新颖,适…...

解决电脑声音正常但就是某些游戏没声音问题
电脑声音正常,玩普遍游戏也正常,就有游戏不出声音 详细介绍经过,不喜欢的请直接跳 第三部分。 一、先说下起因现象。 1 大富翁11 没声音。 前段时间无聊怀旧就买了个大富翁11玩玩,近二十年前的老台式机正常无问题。后来想在性能…...

【UniApp开发小程序】小程序首页(展示商品、商品搜索、商品分类搜索)【后端基于若依管理系统开发】
文章目录 界面效果界面实现工具js页面首页让文字只显示两行路由跳转传递对象将商品分为两列显示使用中划线划掉原价 后端商品controllerservicemappersql 界面效果 【说明】 界面中商品的图片来源于闲鱼,若侵权请联系删除关于商品分类页面的实现,请在我…...
Redis 持久化及集群架构
Redis 持久化及集群架构 本篇技术博文将深入探讨 Redis 持久化机制的原理、配置和使用方式。我们将介绍两种常用的持久化方式:RDB 持久化和 AOF 持久化。您将了解到它们的工作原理、优缺点以及如何根据需求选择合适的持久化方式。 通过深入学习 Redis 持久化及集群…...

FPGA + WS2812采灯控制
文章目录 一、WS2812C-2020-V11、产品概述2、引出端排列及功能3、数据传输时间4、数据传输方法 二、使用WS2812C显示图片1、静态显示2、动态显示 一、WS2812C-2020-V1 1、产品概述 WS2812C-2020-V1是一个集控制电路与发光电路于一体的智能外控LED光源;其外型采用最…...

【视频】使用OBS将MP4推流至腾讯云直播
1、下载OBS OBS官网:https://obsproject.com/ OBS支持Win、Mac、Linux,如果下载速度很慢,建议使用迅雷下载 2、OBS推流设置 2.1 添加场景 默认会有一个“场景”,如果想继续添加可以点击“+”按钮 2.2 添加媒体源 1)点击“来源”窗口中“+”按钮 2)支持的媒体源如…...

Vue基本知识
一、vue入门 Vue为前端的框架,免除了原生js的DOM操作。简化书写。 基于MVVM的思想,实现数据的双向绑定,使编程的重点放在数据上。 1、引入vue.js文件 2、定义vue核心对象,定义数据模型 3、编写视图 //1、引入vue.js <scr…...

item_get_sales-获取商品销量详情
一、接口参数说明: item_get_sales-获取商品销量详情,点击更多API调试,请移步注册API账号点击获取测试key和secret 公共参数 请求地址: https://api-gw.onebound.cn/taobao/item_get_sales 名称类型必须描述keyString是调用key(…...

LangChain手记 Memory
整理并翻译自DeepLearning.AILangChain的官方课程:Memory Memory 使用open ai的API调用GPT都是单次调用,所以模型并不记得之前的对话,多轮对话的实现其实是将前面轮次的对话过程保留,在下次对话时作为输入的message数组的一部分&…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...

华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...