C++STL---priority_queue知识总结及模拟实现

前言

和stack与queue一样,priority_queue也是一种容器适配器。

他的本质其实是堆,作优先级队列的底层需要能够通过随机迭代器访问,所以他的底层是可以由vector和queue实例化,默认情况下priority_queue默认是用vector作为底层实例化,此外我们还可以特指定deque作为他的底层进行实例化。

需要支持随即迭代器,是因为要始终维持堆,优先级队列的本质就是堆。容器适配器通过在需要时自动调用算法函数make_heap,push_heap,pop_heap来始终维持堆。

priority_queue默认是大堆。

priority_queue的使用

priority_queue定义方式

优先级队列有三个模板参数,第一个是元素种类,第二个是用来构造优先级队列的底层容器种类,第三个是构建的方式(大堆还是小堆)。

//这种是不指定底层容器和构造方式的构建,默认底层是vector,构建大堆
priority_queue<int> pq;//这种指定了底层容器和构造方式,我这里设置的底层是deque<int>,构建的是小堆
priority_queue<int,deque<int>,greater<int>> pq1;//我们这里如果要是想要选择构建大堆还是小堆的时候,就只能必须把底层容器的类型也给了
//这是设置缺省参数时的规定,这里不赘述

priority_queue的接口介绍

成员函数功能
push元素入队,通过push_heap函数使其移向堆中适当的位置
pop元素出队,通过pop_heap函数使剩下的元素维持住堆的形式
top获取堆顶元素(优先级最大或最小的元素)
size返回队中有效数据个数
empty判断是否为空
swap交换两个优先级队列中的内容

示例代码:

#include<queue>
#include<iostream>using namespace std;void test1()
{priority_queue<int> pq;pq.push(1);pq.push(2);pq.push(3);pq.push(4);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;priority_queue<int, vector<int>, greater<int>>pq2;pq2.push(1);pq2.push(2);pq2.push(3);pq2.push(4);while (!pq2.empty()){cout << pq2.top() << " ";pq2.pop();}cout << endl;
}int main()
{test1();return 0;
}

如何支持自定义类型使用priority_queue

1.使用仿函数

仿函数就是重载实现 ( ) ,使 ( ) 有实际的意义,因为使用的时候特别像函数调用,所以取名叫仿函数。例如我们有下面的一个类student,我们根据他的成绩_student从小到大进行排序:

#include<iostream>
#include<queue>
#include<vector>
using namespace std;class student
{
public:student(size_t id, size_t grade) :_id(id),_grade(grade){}size_t getId() const{return _id;}size_t getGrade() const{return _grade;}
private:size_t _id;size_t _grade;
};//先创建一个结构体cmp,struct访问权限是public
//里面构造仿函数,我们这里要实现从小到大排序,就要创建小堆,也就是greater的内容
struct cmp
{bool operator()(student& s1,student& s2) {return s1.getGrade() > s2.getGrade();}
};void test1()
{student s1(1,100);student s2(2,80);student s3(3,90);student s4(4,60);vector<student>s;s.push_back(s1);s.push_back(s2);s.push_back(s3);s.push_back(s4);priority_queue<student, vector<student>, cmp> pq;for (auto& e : s){pq.push(e);}while (!pq.empty()){student s = pq.top();cout << s.getId() << endl;pq.pop();}
}int main()
{test1();return 0;
}
2.通过运算符重载来实现自定义实现比较函数

当你使用 priority_queue 时,它需要一个比较函数或者比较对象来决定元素的排序。这个比较函数需要满足一定的要求,特别是它需要能够处理 const 对象。因为priority_queue底层本质上是一个堆,在我们进行插入删除的时候,需要不断调整,在我们调整的过程中是不希望元素的数值改变的。因此在底层我们的编译器只接受const修饰的元素。所以我们在进行operator>或operator<的时候,里面的参数是一定要加上const的。

#include<iostream>
#include<queue>
#include<vector>
using namespace std;class student
{
public:friend bool operator>(student& s1, student& s2);student(size_t id, size_t grade) :_id(id),_grade(grade){}size_t getId() const{return _id;}size_t getGrade() const{return _grade;}
private:size_t _id;size_t _grade;
};//struct cmp
//{
//	bool operator()(student& s1, student& s2) {
//		return s1.getGrade() > s2.getGrade();
//	}
//};bool operator>(const student& s1,const student& s2)//这里一定要加上const,只接收const对象
{return s1.getGrade() > s2.getGrade();
}void test1()
{student s1(1, 100);student s2(2, 80);student s3(3, 90);student s4(4, 60);vector<student>s;s.push_back(s1);s.push_back(s2);s.push_back(s3);s.push_back(s4);priority_queue<student, vector<student>, greater<student>> pq;for (auto& e : s){pq.push(e);}while (!pq.empty()){student s = pq.top();cout << s.getId() << endl;pq.pop();}
}int main()
{test1();return 0;
}

priority_queue的模拟实现

我们前面讲过优先级队列实际就是堆结构,我们要实现它就要先学习两个堆的算法:向上调整算法和向下调整算法。我们这里以构建大堆举例:

向上调整算法

void adjustUp(vector<int>& v,int child)
{int parent = (child - 1) / 2;while (child > 0){if (v[parent] < v[child]){swap(v[parent], v[child]);child = parent;parent = (parent - 1) / 2;}else{break;}}
}//这里我们要构建的是一个大堆,如果儿子的值大于父亲的值就交换位置继续迭代向上迭代

向下调整算法

//堆的向下调整(大堆)
void adjustDown(vector<int>& v, int parent)
{//child记录左右孩子中值较大的孩子的下标int child = 2 * parent + 1;//先默认其左孩子的值较大while (child < v.size()){if (child + 1 < v.size() && v[child] < v[child + 1])//右孩子存在并且右孩子比左孩子还大{child++;//较大的孩子改为右孩子}if (v[parent] < v[child])//左右孩子中较大孩子的值比父结点还大{//将父结点与较小的子结点交换swap(v[child], v[parent]);//继续向下进行调整parent = child;child = 2 * parent + 1;}else//已成堆{break;}}
}

模拟实现

模拟实现实际上就是在上面两个调整算法的基础上,设计几个接口:

namespace cyf
{template<class T>struct less{bool operator()(const T& t1, const T& t2){return t1 < t2;}};template<class T>struct greater{bool operator()(const T& t1, const T& t2){return t1 > t2;}};template<class T,class Container=vector<T>,class Compare=less<int>>class Mypriority_queue{public:void AdjustUp(int child){int parent = (child - 1) / 2;while (child != 0){if (com_(con_[parent], con_[child])){swap(con_[parent], con_[child]);child = parent;parent = (parent - 1) / 2;}else{break;}}}void AdjustDown(int parent){int child = 2 * parent + 1;while (child < con_.size()){if (child + 1 < con_.size() && com_(con_[child], con_[child + 1])){child++;}if (com_(con_[parent], con_[child])){swap(con_[parent], con_[child]);parent = child;child = 2 * child + 1;}else{break;}}}void push(const T& val)//先尾插,再向上调整{con_.push_back(val);AdjustUp(con_.size() - 1);}int size(){return con_.size();}//先交换第一个元素和最后一个元素,之后将换后的最后一个元素删除,之后从0向下调整void pop(){swap(con_[0], con_[size() - 1]);con_.pop_back();AdjustDown(0);}T& top()//两种访问堆顶元素的top()函数{return con_[0];}const T& top() const{return con_[0];}bool empty() const{return con_.empty();}private:Container con_;//存储容器Compare com_;  //比较方式};
}

 以上就是有关优先级队列的全部内容,希望能对大家有所帮助!

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

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

相关文章

智慧博物馆的“眼睛”:视频智能监控技术守护文物安全与智能化管理

近日&#xff0c;位于四川德阳的三星堆博物馆迎来了参观热潮。据新闻报道&#xff0c;三星堆博物馆的日均参观量达1.5万人次。随着暑假旅游高峰期的到来&#xff0c;博物馆作为重要的文化场所&#xff0c;也迎来了大量游客。博物馆作为文化和历史的重要载体&#xff0c;其安全保…

关于vue实现导出excel表,以及导出的excel后的图片超过单元格的问题

实现导出带图标片的excel的方法&#xff0c; 首先&#xff1a; import table2excel from js-table2excel // 导出表格 按钮点击后触发事件 const onBatchExport () > {const column [//数据表单{title: "ID", //表头名称titlekey: "id", //数据ty…

通用图形处理器设计GPGPU基础与架构(四)

一、前言 本文将介绍GPGPU中线程束的调度方案、记分牌方案和线程块的分配与调度方案。 二、线程束调度 在计算机中有很多资源&#xff0c;既可以是虚拟的计算资源&#xff0c;如线程、进程或数据流&#xff0c;也可以是硬件资源&#xff0c;如处理器、网络连接或 ALU 单元。调…

Visual Studio2022中使用.Net 8 在 Windows 下使用 Worker Service 创建守护进程

Visual Studio2022中使用.Net 8 在 Windows 下创建 Worker Service 1 什么是 .NET Core Worker Service1.1 确认Visual Studio中安装了 ASP.NET和Web开发2 创建 WorkerService项目2.1 新建一个WorkerService项目2.2 项目结构说明3 将应用转换成 Windows 服务3.1 安装Microsoft.…

前端书籍翻页效果

目录 前端书籍翻页效果前言代码示例创建模板页面css样式编写js代码 结论 前端书籍翻页效果 前端实现翻书效果&#xff0c;附带vue源码 源码下载地址 前言 实际业务开发中&#xff0c;有时候会遇到需要在前端页面内实现翻书效果的需求&#xff0c;本篇文章就为大家介绍如何使…

09 深度推荐模型演化中的“平衡与不平衡“规律

你好&#xff0c;我是大壮。08 讲我们介绍了深度推荐算法中的范式方法&#xff0c;并简单讲解了组合范式推荐方法&#xff0c;其中还提到了多层感知器&#xff08;MLP&#xff09;。因此&#xff0c;这一讲我们就以 MLP 组件为基础&#xff0c;讲解深度学习范式的其他组合推荐方…

电子设备中丝杆模组高精度重复定位技术的原理!

丝杆模组是由螺旋丝杆和导杆组成的一种机械运动控制系统&#xff0c;通过在导杆内进行旋转&#xff0c;使导杆沿着线性方向进行移动&#xff0c;从而实现机械运动的线性控制。丝杆模组以其高精度、高稳定性和可重复定位的特性&#xff0c;在现代工业自动化和精密制造领域发挥着…

controller-from表单1

mvc模式是spring boot 开发web应用程序主要使用模式&#xff0c;mvc分别代表model模型&#xff0c;view是视图 &#xff0c;controller是控制器 controller是对接用户请求数据调用服务层代码&#xff0c;具体怎么操作 浏览器发送http请求给到dispatcherServlet&#xff08;前…

【操作系统】文件管理——文件存储空间管理(个人笔记)

学习日期&#xff1a;2024.7.17 内容摘要&#xff1a;文件存储空间管理、文件的基本操作 在上一章中&#xff0c;我们学习了文件物理结构的管理&#xff0c;重点学习了操作系统是如何实现逻辑结构到物理结构的映射&#xff0c;这显然是针对已经存储了文件的磁盘块的&#xff0…

无人驾驶的未来:AI如何重塑我们的出行世界

无人驾驶汽车&#xff0c;作为人工智能&#xff08;AI&#xff09;技术的集大成者&#xff0c;正以前所未有的速度改变着我们的出行方式。从机器学习到计算机视觉&#xff0c;再到人工智能生成内容&#xff08;AIGC&#xff09;&#xff0c;AI技术的每一次进步都在为无人驾驶汽…

Linux内核编程(八) 添加自定义目录驱动菜单 (Kconfig文件使用)

本文目录 一、Linux 内核驱动目录二、自定义驱动的Kconfig编写●示例&#xff1a;在 drivers 菜单添加一个自己驱动的子菜单。 三、自写驱动的Makefile编写四、总结 一个Linux内核源码&#xff0c;其中包含了很多驱动程序&#xff0c;对应不同的功能。我们在编译内核时。如果将…

设计模式:真正的建造者模式

又臭又长的set方法 经常进行Java项目开发使用各类starter的你一定见过这种代码&#xff1a; public class SwaggerConfig {Beanpublic Docket api() {return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any()).paths(PathSelectors.any…

【BUG】已解决:ModuleNotFoundError: No module named ‘cv2’

已解决&#xff1a;ModuleNotFoundError: No module named ‘cv2’ 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开…

基于 Web 的家校联系系统的设计与实现

目录 基于 Web 的家校联系系统的设计与实现 一、绪论 &#xff08;一&#xff09;研究背景 &#xff08;二&#xff09; 研究目的 &#xff08;三&#xff09; 研究意义 二、需求分析 &#xff08;一&#xff09; 功能需求 &#xff08;二&#xff09; 性能需求 &#…

开发一个自己的chrom插件

开发一个自己的chrom插件 一、创建一个文件夹 二、配置文件manifest.json 创建名字为&#xff1a;manifest.json的配置文件&#xff0c;模板如下&#xff1a; {"manifest_version": 3,"name": "Hello World Extension","version": …

AV1 编码标准屏幕内容编码技术概述

AV1 屏幕内容编码 为了提高屏幕捕获内容的压缩性能&#xff0c;AV1采用了几种编码工具&#xff0c;例如用于处理屏幕画面中重复模式的内帧内块复制&#xff08;IntraBC&#xff09;&#xff0c;以及用于处理颜色数量有限的屏幕块的调色板模式。 帧内块拷贝 AV1 编码中的 Intra …

【Elasticsearch7.11】reindex问题

参考博文链接 问题&#xff1a;reindex 时出现如下问题 原因&#xff1a;数据量大&#xff0c;kibana的问题 解决方法&#xff1a; 将DSL命令转化成CURL命令在服务上执行 CURL命令 自动转化 curl -XPOST "http://IP:PORT/_reindex" -H Content-Type: application…

Python: 一些python和Java不同的基础语法

文章目录 1. 数据类型2. 字符串的引用3. 字符串拼接4. Python中的报错5. Python中的输入语句(input)6. 运算符(**和//)7. 除法运算8. 注释方法: #或者三引号9. Python中的比较10. Java中用and, or, not代替逻辑运算符11. 多元赋值12. Python不支持自增自减操作13. 在Python中, …

zookeeper基础知识学习

官网&#xff1a;Apache ZooKeeper 下载地址&#xff1a;Index of /dist/zookeeper/zookeeper-3.5.7Index of /dist/zookeeperIndex of /dist/zookeeper/zookeeper-3.5.7 ZK配置参数说明&#xff1a; 1、tickTime2000&#xff1a;通讯心跳时间&#xff0c;zookeeper服务器与客…

笑中带泪《抓娃娃》

【标题】笑中带泪&#xff0c;《抓娃娃》&#xff1a;一场关于成长的中式惊悚喜剧盛宴在这个夏日炎炎的季节里&#xff0c;一部名为《抓娃娃》的电影悄然上映&#xff0c;以沈腾与马丽的黄金搭档再次点燃观众的热情。然而&#xff0c;当笑声在影院回荡时&#xff0c;一股不易察…