【C++】STL优先级队列(priority_queue)

在这里插入图片描述

priority_queue 基本介绍

priority_queue就是优先级队列。其头文件就是queue,但是队列和优先级队列关系不大,两个是不同的数据结构。但二者都是适配器,容器适配器。

在这里插入图片描述

优先级队列中存放的数据是有优先级的。

其内部有以下成员方法,其中常用的就empty, size, top, push, pop。

在这里插入图片描述

直接演示一下常用方法的使用:

我们看到用法几乎是与栈和队列一样。但是这里打印结果是排好序了(降序)。所以,优先级队列默认情况下是大的优先。

优先级队列的适配器

在这里插入图片描述

看其第二个模板参数:class Container = vector,这就是容器适配器。因此我们可以将其底层的容器改为其他的容器(list不行):

在这里插入图片描述

第三个模板参数compare

在这里插入图片描述

跟sort用法很像,sort第三个参数传的是一个对象,比如说给sort传greater()就是降序,而这里传的是类型,比如说传greater就是小堆。可以看到,模板参数缺省值为less,可能有的同学不知道value_type是啥,其实就是我们日常放在容器中的元素类型,就是那个T,T可以为int、char什么的都行。所以我们默认情况下参数 Compare 就是less的类型,那么就是大堆。

在这里插入图片描述

这样就变成了小堆,每次取堆顶的值就是最小值。

  • 传greater时是小堆。
  • 传less时是大堆。

使用优先级队列来解决这个问题:数组中第K个最大的元素

在这里插入图片描述

题目中有要求,必须设计时间复杂度为O(N)的算法。那么先进行排序操作的同学就另寻他路吧。这道题就可以用到优先级队列,就是堆。先把堆建好,然后pop k-1次后的堆顶就是第k大的元素。

class Solution 
{
public:int findKthLargest(vector<int>& nums, int k) {priority_queue<int> pq(nums.begin(), nums.end());while(--k){pq.pop();}return pq.top();}
};

priority_queue 的模拟实现

堆的实现的核心无非就是向上调整和向下调整。而堆虽然逻辑结构上是二叉树,但是实际物理结构就是数组。我们用C++写,默认容器就是vector,因为随机访问数据的次数比较多。我们很多地方就可以直接复用vector中的函数接口,所以就需要自己动手写两个,一个是向上调整,一个是向下调整。

#include<vector>
#include<algorithm>
#include<iostream>namespace Flash
{template<class T, class Container = std::vector<T>,class Compare = less<T>>class priority_queue{private://向上调整void adjust_up(size_t child){Compare com;size_t parent = (child - 1) / 2;while (child > 0){//if (_con[child] > _con[parent])//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);}else{break;}child = parent;parent = (child - 1) / 2;}}//向下调整void adjust_down(size_t parent){Compare com;size_t child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){++child;}//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);}else{break;}parent = child;child = parent * 2 + 1;}}public:void push(const T& x){_con.push_back(x);adjust_up(_con.size() - 1);}void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);}const T& top(){return _con[0];}bool empty()const{return _con.empty();}int size()const{return _con.size();}private:Container _con;};template<class T>struct less{bool operator()(const T& L, const T& R){return L < R;}};template<class T>struct greater{bool operator()(const T& L, const T& R){return L > R;}};}

上面基本功能的是实现了,但是问题是不能控制大小堆,那我们可以像库中那样,再搞一个模板参数,传一个仿函数来实现大小堆的控制。

仿函数

仿函数就是一个类,里面重载了()运算符。

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

第一个ls(1, 2)乍一看就像是函数调用,但实际上就是类匿名对象调用了operator()。

在这里插入图片描述

再来个greater:

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

这就是仿函数,用类来重载()来实现。调用的时候就像函数一样,在C语言阶段学过的qsort,传比较的那个参数的时候要传函数指针,但是函数指针太麻烦了,所以C++为了不再用函数指针,就搞了仿函数。

那么此时我们就可以搞第三个模板参数了。

在这里插入图片描述

传的是类型。然后把我们向上调整和向下调整中的代码改一改:

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

上面的priority_queue、less、greater都是在一个命名空间FangZhang中的,所以除了vector是复用的,剩下的都是手写的,less和greater就是刚写出来的那两个,可以直接用。

在这里插入图片描述

再来强调一点:

假如说一个对象vector v,我们用sort时,传参是sort(v.begin(), v.end(), less()),而这堆这是定义对象传模板参数priority_queue<int, vector, less>,前者是传匿名对象,后者是传类型。是不一样的。不要搞混。

栈和队列还有优先级队列都是容器适配器,就是可以改变其底层所使用的容器,从而能够用不同的容器来实现其底层的函数接口。

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

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

相关文章

【乳腺肿瘤诊断分类及预测】基于PNN概率神经网络

课题名称&#xff1a;基于PNN的乳腺肿瘤诊断分类及预测 版本日期&#xff1a;2023-06-15 运行方式: 直接运行PNN0501.m 文件即可 代码获取方式&#xff1a;私信博主或QQ&#xff1a;491052175 模型描述&#xff1a; 威斯康辛大学医学院经过多年的收集和整理&#xff0c;建…

Windows10更新失败 错误 0x80070643、KB5034441的解决方法之二

Windows10更新失败 错误 0x80070643、KB5034441 在知乎Windows10更新失败 错误 0x80070643、KB5034441的原因分析和几个解决方法 - 知乎 参考文章进行操作&#xff0c;更详细信息自己看上面链接。 我电脑的硬盘是mbr格式&#xff0c;而且没有划分恢复分区。 Microsoft Windo…

性能测试工具架构

背景 性能测试工具&#xff08;LoadRunner为例&#xff09; 性能测试工具通常是指那些用来支持压力、负载测试&#xff0c;能够录制和生成脚本、设置和部署场景、产生并发用户和向系统施加持续压力的工具。 性能测试工具录制的是服务端与应用之间的通信数据&#xff0c;而不是…

canvas自定义扩展方法:文字自动换行

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

Android进阶之路 - ViewPager2 比 ViewPager 强在哪?

我记得前年&#xff08;2022&#xff09;面试的时候有被问到 ViewPager 和 ViewPager2 有什么区别&#xff1f;当时因为之前工作一直在开发售货机相关的项目&#xff0c;使用的技术要求并不高&#xff0c;所以一直没去了解过 ViewPager2~ 去年的时候正好有相关的功能需求&#…

JavaScript入门

第二个知识点&#xff1a;javascript的基本语法 定义变量 在JavaScript里面&#xff0c;没有int&#xff0c;string 之类的数据类型&#xff0c;只有 var var num 1; var string "天玄地号"; 在javascript中&#xff0c;写完一句语句之后可以不加分号&#xff…

【lesson30】MySQL事务一致性和再次理解隔离性

文章目录 一致性(Consistency)如何理解隔离性2数据库并发的场景有三种&#xff1a;读-写3个记录隐藏列字段undo log日志模拟 MVCC思考Read ViewRR 与 RC的本质区别测试RR 与 RC的本质区别分析 一致性(Consistency) 事务执行的结果&#xff0c;必须使数据库从一个一致性状态&am…

【Java】实现图书管理系统

文章目录 1. 设计背景2. 需求分析3. 设计思路4. 实现4.1 book包4.1.1 Book类4.1.2 BookList类(书架) 4.2 user包4.2.1 User 类4.2.2 AdminUser类&#xff08;管理员用户&#xff09;4.2.3 NormalUser类&#xff08;普通用户&#xff09; 4.3 operation包4.3.1 IOPeration接口4.…

企业数字化转型有哪些难点?

企业数字化转型虽然带来诸多好处&#xff0c;但往往是一个复杂且充满挑战的过程。以下是组织在数字化转型计划中可能面临的一些常见困难&#xff1a; 1.抵制变革&#xff1a; 员工抵制&#xff1a;员工可能会抵制对其既定工作流程、工具和流程的更改。人们可能会担心工作被取…

周期承压下的徐工机械:收入持续负增长,大肆并购风险犹存

撰稿|行星 来源|贝多财经 工程机械行业的发展程度是衡量工业化水平的关键指标&#xff0c;亦是一直以来备受国家与市场关注的高成长板块。 在探索新发展增量的大军中&#xff0c;徐工机械&#xff08;SZ:000425&#xff09;活跃工程机械市场&#xff0c;寻求着利润与品质的最…

在 python 中调用 C/C++

Python 是一种很好用的胶水语言&#xff0c;利用Python的简洁和C的高效&#xff0c;基本可以解决99%的问题了&#xff0c;剩下那 1% 的问题也就不是问题了&#xff0c;毕竟不是所有问题都可解。 一般的&#xff0c;Python和C的交互分为这两种情况&#xff1a; 用C扩展Python&…

【开源】SpringBoot框架开发海南旅游景点推荐系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四、核心代码4.1 随机景点推荐4.2 景点评价4.3 协同推荐算法4.4 网站登录4.5 查询景点美食 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的海南旅游推荐系统&#xff…