当前位置: 首页 > article >正文

C++堆(优先队列)priority_queue

堆原理

堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆(大根堆);每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆(小根堆)。
从堆的概念可知,堆是一棵完全二叉树,因此可以使用层序的规则采用顺序的方式来高效存储。
完全二叉树,我的理解:任何节点的子节点只有以下三种情况:
一,没有孩子。二,有两个孩子。三,只有左孩子。
不会出现只有右孩子,没有左孩子的情况。
cur节点如果左孩子还有后代,则cur一定有右孩子。
性质一根节点的编号1,根节点的左孩子编号2,根节点的右孩子编号3。2的孩子编号为:4,5。3的孩子编号:6,7。即节点i的孩子是:i × \times × 2和i × \times × 2+1。节点i的父亲节点是 i/2。即BFS序,先层次(行),再列。
由于C++的标准库有现场的类和函数,所以无需关心具体细节。

向量模拟堆

建立大根堆

我们利用make_heap建立大根堆:

const int N = 5;
			int a[N] = { 10,20,30,40,50 };
			make_heap(a, a + N);

结果为 {50, 40, 30, 10, 20} 时间复杂度O(n)
在这里插入图片描述

增加元素

std::push_heap 会重排容器最后一个元素,使得最大元素(对于最大堆)或最小元素(对于最小堆)位于容器的开头。时间复杂度为 O(log n),其中 n 是堆的大小。只会影响此节点的祖先。
必须先调用make_heap,再调用push_heap,否则会除错。比如:

const int N = 6;
vector<int> a = { 10,20,30,40,50,35 };
			//make_heap(a.begin(),a.end());
			push_heap(a.begin(), a.end());

结果为:{35,20,10,40,50,30)
正确的例子:

		vector<int> a = { 10,20,30,40,50 };
			make_heap(a.begin(),a.end());
			a.push_back(35);
			push_heap(a.begin(), a.end());

结果为:{50,40,35,10,20,30}

删除元素

std::pop_heap 将堆中的最大元素(对于最大堆)或最小元素(对于最小堆)移动到容器的末尾,并保持剩余元素的堆属性。并不会直接移除元素,而是将最大或最小元素移到容器的末尾。需要手动调用 pop_back() 来移除该元素。std::pop_heap 之后,容器的前 n-1 个元素仍然是一个有效的堆。时间复杂度为 O(log n)。用堆的最后一个元素替换根,确保跟换的节点大于两个孩子,否则和较大的孩子互换。

vector<int> a = { 10,20,30,40,50 };
			make_heap(a.begin(),a.end());
			pop_heap(a.begin(), a.end());
			a.pop_back();

结果为:{40,20,30,10}

建立小根堆

vector<int> a = { 10,20,30,50,40 };
			make_heap(a.begin(),a.end(),greater<>());

结果不变。

C++堆(优先队列)。

建立堆

	vector<int> a = { 10,20,30,50,40 };
			priority_queue<int> maxHeap(a.begin(), a.end());
			priority_queue<int, vector<int>, greater<>> minHeap(a.begin(), a.end());

大根堆为:{50,40,30,20,10} 小根堆和a同。

其它函数

获取堆顶元素
auto cur = maxHeap.top();
弹出堆顶元素
maxHeap.pop();
增加元素
maxHeap.push(3);

解题技巧

双堆(对顶堆)

总共有n个数,大根堆记录较小的n/2个数,小根堆记录余下的数。方便求中位数。

懒删除堆

记录堆中要删除的元素,如果堆顶的元素是要删除的元素,则删除。解决:堆无法删除非堆顶元素的问题。

反悔堆

‌反悔堆‌是一种特殊的贪心算法,它允许在贪心选择后进行反悔,从而调整之前的决策。反悔堆通过维护一个堆(最大堆或最小堆)来快速找到当前最优解,并在必要时进行反悔操作,以获得全局最优解。
‌课程表问题‌:选择最优的课程组合,避免时间冲突。
‌最低加油次数问题‌:在加油站点选择最优路径,确保到达目的地。
‌工作调度问题‌:在截止日期前完成收益最大的工作,避免时间冲突。

题解

已发布难度分
【 贪心 临项交换 多指针】2931. 购买物品的最大开销1822
【贪心 堆 】3081. 替换字符串中的问号使分数最小1904
【反悔贪心 反悔堆】1642. 可以到达的最远建筑1962
大根堆】【反悔堆】【反悔贪心】【C++算法】871 最低加油次数2074
【堆 优先队列】2402. 会议室 III2092
【堆 优先队列】1354. 多次求和构造目标数组2014
【离线查询 堆 优先队列】1383. 最大的团队表现值2091
【懒删除堆 优先队列】1172. 餐盘栈2109
【对顶堆 优先队列】2102. 序列顺序查询2158
【映射 懒惰堆】1912. 设计电影租借系统2181
【离线查询 堆】2503. 矩阵查询可获得的最大分数2195
【堆 优先队列】2163. 删除元素后和的最小差值2225
【堆 优先队列】857. 雇佣 K 名工人的最低成本2259
【有序集合 堆 优先队列】1606. 找到处理最多请求的服务器2275
【数据结构】【双堆】【滑动窗口】3013. 将数组分成最小总代价的子数组 II2277
【堆 优先队列 第k大】2551. 将珠子放入背包中2402
【反悔堆 反悔贪心】2813. 子序列最大优雅度2582
【广度优先搜索】【堆】【C++算法】407. 接雨水 II难度未知
【堆 优先队列】23. 合并 K 个升序链表难度未知
【对顶堆 优先队列】295. 数据流的中位数难度未知
【贪心 堆 优先队列】502. IPO难度未知
【反悔堆 优先队列 临项交换 决策包容性】630. 课程表 III难度未知
【堆 (优先队列) 扫描线】218. 天际线问题难度未知
陆续发布,预计20241118之前发完难度分
2233. K 次增加后的最大乘积1685
1942. 最小未被占据椅子的编号1695
1801. 积压订单中的订单总数1711
2462. 雇佣 K 位工人的总代价1763
1834. 单线程 CPU1797
1792. 最大平均通过率1817
1882. 使用服务器处理任务1979

扩展阅读

我想对大家说的话
工作中遇到的问题,可以按类别查阅鄙人的算法文章,请点击《算法与数据汇总》。
学习算法:按章节学习《喜缺全书算法册》,大量的题目和测试用例,打包下载。重视操作
有效学习:明确的目标 及时的反馈 拉伸区(难度合适) 专注
闻缺陷则喜(喜缺)是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛
失败+反思=成功 成功+反思=成功

视频课程

先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771
如何你想快速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。


http://www.kler.cn/news/317198.html

相关文章:

  • 删除topic提示admin token
  • The NCCoE’s Automation of the CMVP
  • 【Oauth2整合gateway网关实现微服务单点登录】
  • k8s云平台部署文档
  • 【MySQL】使用C语言连接数据库
  • Http-浏览器发出⼀个请求到收到响应经历了哪些步骤?
  • 如何使用GLib的单向链表GSList
  • 【软考】cpu的功能
  • Linux环境的JDK安装
  • 【爬虫工具】小红书评论高级采集软件
  • 无人机之可承受风速的影响因素
  • C++ STL容器(二) —— list 底层剖析
  • 信息安全概论期末复习笔记
  • ubuntu如何进行切换内核版本全教程
  • 交易验证码识别数据集
  • ArcGIS Desktop使用入门(三)图层右键工具——拓扑(上篇:地图拓扑)
  • Qanything 2 0 源码解析系列3 文件解析服务
  • golang学习笔记8-运算符与输入
  • torch.stack
  • docker修改默认存储路径和网段
  • [ffmpeg] 录制
  • 2023年06月中国电子学会青少年软件编程(Python)等级考试试卷(二级)答案 + 解析
  • Apache的ab压力测试工具与性能监控
  • 【第十一章:Sentosa_DSML社区版-机器学习之分类】
  • windows C++ 并行编程-使用消息块筛选器
  • PyCharm安装详情教程
  • 基于OpenCV的单目测距
  • Apache Iceberg Architecture—Iceberg 架构详解
  • Seata学习笔记
  • 使用python写按键程序