【C++】STL优先级队列(priority_queue)功能介绍以及模拟实现

news2024/12/23 18:03:29

优先级队列

    • 前言
    • 正式开始
      • priority_queue 基本介绍
      • 优先级队列的适配器
      • 第三个模板参数compare
      • 模拟实现priority_queue
        • 仿函数

在这里插入图片描述

前言

点进来的小伙伴不知道学过数据结构里的堆没有,如果学过的话,那就好说了,优先级队列就是堆,如果没学过,没关系,可以参考一下我之前写的一篇关于堆的博客,可以点进去看看:【数据结构】堆(包含堆排序和TOPK问题)

那么了解过堆了的话,我就不讲那么细致了,就把STL中给的接口说一遍,然后模拟实现一下,再说一下适配器就好了。

正式开始

还是cpluplus这个网站:queue

在这里插入图片描述

priority_queue 基本介绍

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

在这里插入图片描述
关于适配器和仿函数会在最后的时候讲。

先说基本的。

根据优先级队列的名字就可以知道其存放的数据是有优先级的。
里面就下面这几个函数:
在这里插入图片描述
而且常用的就empty, size, top, push, pop。

意思就不讲了,看过我前面string、vector、list、栈和队列的话,肯定是知道这些函数是干啥的。

我就直接演示一下就好:
在这里插入图片描述
用法几乎是与栈和队列一样。
但是这里是打印结果排好序了,降序。

所以,优先级队列默认情况下是大的优先。打印升序等会讲。

优先级队列的适配器

在这里插入图片描述

看其第二个模板参数:class Container = vector<T>
这就是容器适配器。

看过前一篇栈和队列的话估计你就懂什么意思了,如果不懂适配器是啥,可以看看:STL栈和队列

我们可以将其底层的容器改为其他的容器,像我们上一篇讲的deque就可以:
在这里插入图片描述
list是不行的,至于什么行什么不行在模拟实现的时候再说。

第三个模板参数compare

在这里插入图片描述

其实前面几篇中用到算法库中的sort时已经见过了,但是当时并不知道其底层是啥样的,那么这篇就能了解一下了,但这里就还是先说咋用,最后模拟实现的时候再说底层。

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

给个例子:
在这里插入图片描述
这样就变成了小堆,每次取堆顶的值就是最小值。

这里要记住:
传greater时是小堆。
传less时是大堆。

这样基本用法就算讲好了,不要说这点怎么够,就几个函数,没什么好讲的,重点在后面。

带大家来做一道题。
题目链接:数组中的第K个最大元素

在这里插入图片描述
题目中有要求,必须设计时间复杂度为O(N)的算法。

那么想到排序的同学就另寻他路吧。

这道题就可以用到优先级队列,就是堆。
先把堆建好,然后pop k-1次后的堆顶就是第k大的元素。

代码如下:

class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
    priority_queue<int> poq(nums.begin(), nums.end());

    while(--k)
        poq.pop()return poq.top();
}
};

然后就是最重要的模拟实现了。

模拟实现priority_queue

学过堆的同学应该都知道,堆的实现的核心无非就是向上调整和向下调整。

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

先把基本的给出:
在这里插入图片描述

push和pop要用到向上调整和向下调整:
在这里插入图片描述
记得这两个要设置为私有。

然后把基本的接口给出:
在这里插入图片描述

测试一下:
在这里插入图片描述

上面基本功能的是实现了,但是还是有点问题的,就是如何控制大小堆?
不能说别人用的时候还要把代码改一下才行,这样实现出来的东西也太拉垮了,能不能像库中那样,再搞一个模板参数,传一个仿函数来实现大小堆的控制。

肯定是可以的,但那么先说一下仿函数是什么。

仿函数

很简单,不要被名字吓到。

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

看:
在这里插入图片描述
这就是那个less。非常的简单。

用一下:
在这里插入图片描述
第一个ls(1, 2)乍一看就像是函数调用,但实际上就是类对象调用了operator()。

可能看起来不是很熟悉,看这个:
在这里插入图片描述
这个看起来就相对熟悉一点了,sort里传参就是红色框出来的匿名对象。

再来个greater:
在这里插入图片描述
测试:

在这里插入图片描述

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

那么此时我们就可以搞第三个模板参数了。
在这里插入图片描述
传的是类型。
然后把我们向上调整和向下调整中的代码改一改:
在这里插入图片描述
上面的priority_queue、less、greater都是在一个命名空间FangZhang中的,所以除了vector是复用的,剩下的都是手写的,less和greater就是刚写出来的那两个,就可以直接用了。

测试一下:
在这里插入图片描述
完全是可以用的。
再用一下库中的:
在这里插入图片描述
也是可以的。

再来强调一点。

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

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

下一篇讲迭代器适配器。

到此结束。。。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ViewModel实例什么时候被回收

作者&#xff1a;TechMix 一、ViewModel存在的意义&#xff1f; ViewModel做为JetPack中重要的组件&#xff0c;翻译成中文就是“视图模型”&#xff0c;根据分离关注点原则&#xff0c;ViewModel的出现&#xff0c;主要是为了分担Activity中的职责&#xff0c;专门用于存放和…

谷歌云 | Document AI 引入了强大的新自定义文档拆分器来自动化文档处理

【本文由Cloud Ace整理发布。Cloud Ace是谷歌云全球战略合作伙伴&#xff0c;拥有 300 多名工程师&#xff0c;也是谷歌最高级别合作伙伴&#xff0c;多次获得 Google Cloud 合作伙伴奖。作为谷歌托管服务商&#xff0c;我们提供谷歌云、谷歌地图、谷歌办公套件、谷歌云认证培训…

Orange:一个基于 Python 的数据挖掘可视化平台

本篇介绍一个适合初学者入门的机器学习工具。 Orange 简介 Orange 是一个开源的数据挖掘和机器学习软件。Orange 基于 Python 和 C/C 开发&#xff0c;提供了一系列的数据探索、可视化、预处理以及建模组件。 Orange 拥有漂亮直观的交互式用户界面&#xff0c;非常适合新手进…

测试用例(3)

功能测试用例方法&#xff1a; 等价类 边界值 因果图 正交实验分解法 判定表驱动分析方法 非功能性的测试用例方法&#xff1a; 错误推测法 功能图分析方法 场景&#xff1a; 场景设计方法 1) 在任何情况下都必须使⽤边界值分析⽅法&#xff0c;经验表明⽤这种⽅法设…

CGT Asia嘉年华|3D细胞培养与类器官研发峰会10月广州召开

类器官指利用成体干细胞或多能干细胞进行体外三维&#xff08;3D&#xff09;培养而形成的具有一定空间结构的组织类似物&#xff0c;是近10年来干细胞领域发展最快的研究热点之一。2022年&#xff0c;FDA 通过现代化法案 2.0&#xff0c;批准全球首个完全基于“类器官芯片”研…

pandas 笔记:pivot_table 数据透视表\pivot

1 基本使用方法 pandas.pivot_table(data, valuesNone, indexNone, columnsNone, aggfuncmean, fill_valueNone, marginsFalse, dropnaTrue, margins_nameAll, observedFalse, sortTrue)2 主要参数 dataDataFramevalues要进行聚合的列index在数据透视表索引&#xff08;index…

# Linux下替换删除文件中的颜色等控制字符的方法

Linux下替换删除文件中的颜色等控制字符的方法 文章目录 Linux下替换删除文件中的颜色等控制字符的方法1 Linux下的控制字符&#xff08;显示的文字并不是他本身&#xff09;&#xff1a;2 颜色字符范例&#xff1a;3 替换4 最后 我们在shell编程显示输出时&#xff0c;会定义文…

【Java】一个简单的接口例子(帮助理解接口+多态)

要求&#xff1a; 请实现笔记本电脑使用USB鼠标、USB键盘的例子 1. USB 接口&#xff1a;包含打开设备、关闭设备功能 2. 笔记本类&#xff1a;包含开机功能、关机功能、使用 USB 设备功能 3. 鼠标类&#xff1a;实现 USB 接口&#xff0c;并具备点击功能 4. 键盘类&am…

人才输送|我的“捷码低代码工程师”转型之路!

最新职位 招聘岗位&#xff1a;低代码工程师 需求公司&#xff1a;上海北斗西虹桥基地 应聘条件&#xff1a;1、本科以上&#xff0c;最好硕士&#xff1b;2、有三年以上开发经验&#xff1b; 工作内容&#xff1a;带领团队用捷码低代码平台进行项目开发。 工作地点&#xff1a…

长城汽车Hi4技术品牌成果初现,大象转身必将势不可挡

今年1-6月&#xff0c;长城汽车销售52万辆&#xff0c;新能源车型销售9.3万辆&#xff0c;同比增长47%&#xff1b;智能新能源新产品密集上市&#xff0c;新能源销量与占比逐月攀升&#xff0c;6月销售超2.6万辆&#xff0c;占比突破25%&#xff0c;皆创历史新高&#xff1b; 全…

文档翻译成中文怎么弄?今天分享文档翻译免费要怎么弄

有一天&#xff0c;小华来到了一个外国小镇。然而&#xff0c;他发现镇上的路牌、菜单和旅游手册都是用外语写的&#xff0c;让他感到非常困扰。他不知道该去哪里游玩&#xff0c;也无法理解当地的文化和历史。他非常喜欢这个小镇的风景&#xff0c;但是他无法读懂他们这里的一…

【Linux -- 查看进程--ps,top,pstree】

Linux – 查看进程 文章目录 Linux -- 查看进程一、查看进程 -- ps二、动态查看进程的变化 -- top三、pstree -- 可以找进程之间的相关性总结 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、查看进程 – ps 更详细的可以通过man ps查看 ps aux …

深入理解Java虚拟机(三)垃圾收集器与内存分配策略

Java与C之间有一堵由内存动态分配和垃圾收集技术所围成的高墙&#xff0c;墙外面的人想进去&#xff0c;墙里面的人却想出来。 Java内存运行时区域的各个部分&#xff0c;其中程序计数器、虚拟机栈、本地方法栈3个区域随线程而生&#xff0c;随线程而灭&#xff0c;栈中的栈帧随…

echarts图例对齐

富文本不生效&#xff0c;是没有设置lineHeight

【运维】shell监控脚本结合钉钉机器人实现服务及服务器监控告警

文章目录 前言一、监控shell脚本和钉钉机器人二、创建钉钉机器人&#xff1a;1.在钉钉群聊里点击设置2.在设置里点击机器人选项3.再点击添加机器人4.再点击选择自定义机器人5.设置机器人名称、是否加密、是否限制ip、以及触发关键字6.获取机器人的Webhook地址 三、编写监控脚本…

MySQL表关联更新

背景&#xff1a; 有两张表&#xff0c;一张class信息表&#xff0c;一张student信息表&#xff0c;但student表里的信息存在错误&#xff0c;需要用class表中的信息去更新student表数据。 方法一&#xff1a; update student_info s set class_name (select class_name fr…

一本通12951917:装箱问题

不知道说什么废话好了 题目 装箱问题 描述 有一个箱子容量为V&#xff08;正整数&#xff0c;0&#xff1c;&#xff1d;V&#xff1c;&#xff1d;20000&#xff09;&#xff0c;同时有n个物品&#xff08;0&#xff1c;n&#xff1c;&#xff1d;30)&#xff0c;每个物品…

Spring 的依赖注入

Spring 的依赖注入 文章目录 Spring 的依赖注入每博一文案1. 依赖注入1.1 构造注入1.1.1 通过参数名进行构造注入1.1.2 通过参数的下标&#xff0c;进行构造注入1.1.3 不指定参数下标&#xff0c;不指定参数名字&#xff0c;通过自动装配的方式 1.2 set 注入 2. set注入的各种方…

uniapp 小程序 picker 日期时间段选择(精确到年月日时分+周几)

效果图&#xff1a; picker时间选择器 精确到年月日时分周几 需要引入moment.js&#xff0c;有可能引入后在项目内会报错&#xff0c;可以考虑把选择日期作为一个组件引入 1、timepage.vue组件封装 <template><view><picker mode"multiSelector" :va…

人才输送|捷码帮我走出求职迷茫期!

大家好&#xff0c;我是边文军。 很荣幸应余老师之邀&#xff0c;在这里和各位兄弟姐妹分享应聘青岛英哲低代码工程师的求职经历&#xff0c;希望能给大家提供点帮助。 01 自我介绍 先来做一个自我介绍吧&#xff01;我是计算机专业出身&#xff0c;学的移动应用开发专业。学…