堆的实现以及应用
💓博主个人主页:不是笨小孩👀
⏩专栏分类:数据结构与算法👀 刷题专栏👀 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数组的一部分&…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
