优先级队列priority_queue以及仿函数的使用
目录
- 优先级队列priority_queue
- priority_queue的模拟实现
- 仿函数
优先级队列priority_queue
优先级队列priority_queue是一种容器适配器,根据严格的弱排序标准,它默认第一个元素总是它所包含的元素中最大的
优先级队列默认使用vector作为底层存储数据的容器,在vector上又使用了堆排序的算法对数据进行排序,所以priority_queue就是堆。注意:priority_queue默认情况下是大堆
priority_queue是存在<queue>文件中,要使用只需要包queue文件就可以
所以以后有需要用到堆的位置,我们就不用手动实现一个堆了,可以直接使用
priority_queue就可以
下面是优先级队列的定义:
template <class T, class Container = vector<T>,class Compare = less<typename Container::value_type> > class priority_queue;
第一个模板参数是放在适配器容器内元素的类型
第二个模板参数是适配器,默认为vector
第三个模板参数是一个仿函数,默认是less,为了保证默认是大堆
| 函数 | 接口说明 |
|---|---|
| priority_queue() | 构造一个空的优先级队列 |
| priority_queue (InputIterator first, InputIterator last) | 用[first,last)迭代器区间构造一个优先级队列 |
| empty() | 判空 |
| top( ) | 返回优先级队列中最大(最小元素),即堆顶元素 |
| push(x) | 在优先级队列中插入元素x |
| pop() | 删除优先级队列中最大(最小)元素,即堆顶元素 |
下面我们使用优先级队列尝试一下:
void test1()
{priority_queue<int> pq;pq.push(1);pq.push(6);pq.push(9);pq.push(3);pq.push(0);pq.push(2);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}//输出 9 6 3 2 1 0 cout << endl;
}
如果我们先实现一个小堆,只需要改变第三个模板参数就可以,让第三个模板参数为greater<T>,因为我们指定了第三个模板参数,所以我们还需手动显式传第二个模板参数
下面我们实现一个小堆的priority_queue:
void test1()
{priority_queue<int,vector<int>,greater<int>> pq;pq.push(1);pq.push(6);pq.push(9);pq.push(3);pq.push(0);pq.push(2);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}//输出 0 1 2 3 6 9cout << endl;
}
priority_queue的模拟实现
因为优先级队列的底层是堆排序,所以我们先完成堆排序中的向下调整,和向上调整
void AdjustDown(int parent)
{Compare com;size_t child = 2 * parent + 1;while (child < _con.size()){if (child + 1 < _con.size() && _con[child]<_con[child + 1]){child++;}if (_con[parent]< _con[child]){std::swap(_con[child], _con[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}void AdjustUp(int child)
{Compare com;int parent = (child - 1) / 2;while (parent >= 0){if (_con[parent]< _con[child]){std::swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}
push函数,就是,先向底层适配器中插入一个元素,然后再调用向上调整法
void push(const T& t)
{_con.push_back(t);AdjustUp(_con.size() - 1);}
pop函数,先把适配器中首元素和尾元素交换,然后删除尾元素,再调用向下调整法
void pop()
{std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);
}
还有几个实现起来很简单的函数:
bool empty()
{return _con.empty();
}const T& top()
{return _con[0];
}size_t size()
{return _con.size();
}
当前完整代码:
namespace my_priority_queue
{template<class T, class Container = std::vector<T>>class priority_queue{private:void AdjustDown(int parent){size_t child = 2 * parent + 1;while (child < _con.size()){if (child + 1 < _con.size() && _con[child]<_con[child + 1]){child++;}if (_con[parent]< _con[child]){std::swap(_con[child], _con[parent]);parent = child;child = 2 * parent + 1;}else{break;}}}void AdjustUp(int child){int parent = (child - 1) / 2;while (parent >= 0){if (_con[parent]< _con[child]){std::swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}public:priority_queue(){}template<class InputIterator>priority_queue(InputIterator first, InputIterator last){while (first != last){_con.push_back(*first);first++;}for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--){AdjustDown(i);}}void push(const T& t){_con.push_back(t);AdjustUp(_con.size() - 1);}void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}bool empty(){return _con.empty();}const T& top(){return _con[0];}size_t size(){return _con.size();}private:Container _con;};
}
此时,我们已经实现了一个大堆的优先级队列
那么怎么实现小堆的优先级队列呢?当前我们只能去修改向下调整和向上调整中比较大小的部分:

这其实挺麻烦的,有没有什么方法可以使大堆和小堆的优先级队列可以秒切换呢?
答案就是:可以使用仿函数
仿函数
仿函数也叫函数对象,这个类的对象可以像函数一样使用,使一个类的使用看上去像一个函数
其实现就是类中实现一个operator(),有了对括号的重载,就可以让这个类的对象像函数一样使用
下面就是一个仿函数:
class IntLess
{
public:bool operator()(int x,int y){return x < y;}};
怎么使用仿函数呢?毕竟仿函数是一个类,所以我们使用时需要先实例化一个对象出来
然后将这个对象像使用函数一样使用
在对象后面加上(),该传参就传参
void test2()
{IntLess LessFunc;cout<<LessFunc(1,2)<<endl;//仿函数的使用
}
LessFunc(1,2)会被处理成:LessFunc.operator()(1,2)
接下来,用仿函数完善模拟实现的优先级队列
template<class T>
struct Less//首字母大写,为了与库中的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 = std::vector<T>,class Compare = Less<T>>
然后,然后将向上调整和向下调整中大小判断部分改为仿函数
void AdjustDown(int parent)
{Compare com;//仿函数使用前,实例化出一个对象size_t 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])){std::swap(_con[child], _con[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}void AdjustUp(int child)
{Compare com;//仿函数使用前,实例化出一个对象int parent = (child - 1) / 2;while (parent >= 0){if (com(_con[parent], _con[child])){std::swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}
相关文章:
优先级队列priority_queue以及仿函数的使用
目录 优先级队列priority_queuepriority_queue的模拟实现仿函数 优先级队列priority_queue 优先级队列priority_queue是一种容器适配器,根据严格的弱排序标准,它默认第一个元素总是它所包含的元素中最大的 优先级队列默认使用vector作为底层存储数据的…...
java+ssm+mysql水费管理系统
项目介绍: 使用javassmmysql开发的用户水费管理系统,系统包含超级管理员,系统管理员、用户角色,功能如下: 超级管理员:管理员管理、用户管理、用水管理(用水记录、缴费提醒)、水费…...
搭建最简单的SpringBoot项目
1、创建maven项目 2、引入父pom <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.15</version> </parent> 3、引入springboot-web依赖 <dependency…...
Windows系统手动重新生成性能计数器
症状 使用性能监视器工具时,某些计数器可能缺失或不包含计数器数据。 性能计数器库可能已损坏,需要重新生成。 应用程序日志中可能会出现以下错误: Log Name: Application Source: Microsoft-Windows-IIS-W3SVC-PerfCounters Event ID…...
go elsaticsearch demo
安装 // elasticsearch sdk go get -u github.com/elastic/go-elasticsearch/v7 //操作json go get "github.com/tidwall/gjson" go get "github.com/aquasecurity/esquery"demo package esexampleimport ("bytes""context""en…...
小游戏分发平台如何以技术拓流?
2023年,小游戏的发展将受到多方面的影响,例如新技术的引入、参与小游戏的新玩家以及游戏市场的激烈竞争等。首先,新技术如虚拟现实(VR)、增强现实(AR)和机器人技术都可以带来新颖的游戏体验。其…...
力扣|找出和所对应的两数的下标
从零开始刷力扣(bushi 题目放在这: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值target的两个整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一…...
使用命令行创建仓库
如果你还没有任何代码,可以通过命令行工具创建一个全新的Git仓库并初始化到本项目仓库中。 git clone https://e.coding.net/***/neurosens.git cd neurosens echo "# neurosens" >> README.md git add README.md git commit -m "first commi…...
ESLint 中的“ space-before-function-paren ”相关报错及其解决方案
ESLint 中的“ space-before-function-paren ”相关报错及其解决方案 出现的问题及其报错: 在 VScode 中,在使用带有 ESLint 工具的项目中,保存会发现报错,并且修改好代码格式后,保存会发现代码格式依然出现问题&…...
docker常用中间件安装
文章目录 1、前言2、中间件安装2.1、mysql2.2、gitlab容器2.3、nacos2.4、redis2.5、xxljob2.6、zipkin2.7、sentinel2.8、seata2.8.1、获取镜像2.8.2、运行容器并获取配置 2.9、rockerMQ2.9.1、rockerMQ-namesrv2.9.2、rockerMQ-broker2.9.3、rockerMQ-console 2.10、jenkins2…...
Camunda 7.x 系列【44】修改流程实例
有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot 版本 2.7.9 本系列Camunda 版本 7.19.0 源码地址:https://gitee.com/pearl-organization/camunda-study-demo 文章目录 1. 概述2. 案例演示2.1 回退2.2 子流程2.3 多实例加签1. 概述 流程模型中,执行活动需要按…...
无频闪护眼灯哪个好?什么是无频闪
随着科技的不断发展,工作时使用电子设备越来越普遍,如何保护我们的眼睛不受蓝光、频闪等危害就变得极其重要了。护眼台灯,顾名思义就是保护眼睛的台灯,其工作原理是在光源处使用特殊的防蓝光灯珠,并通过控制电流的稳定性来达到防频…...
css网格布局
css网格布局 常用属性 display: grid; //开启网格grid-template-columns: 2fr 1fr 1fr 1fr 1fr; //设置多少列每列宽度grid-gap: 10px; // 设置表格之间间距grid-template-rows: 50px 50px 50px 50px; // 设置多少行 每行的高度grid-column : 1 //占据位置 占据1格grid-colu…...
Hadoop -HDFS常用操作指令
1.启动HDFS hadoop/sbin/start-dfs.sh2.关闭 HDFS hadoop/sbin/stop-dfs.sh3. 在HDFS中创建文件夹 #老版本 hadoop fs -mkdir -p path #新版本 hadoop dfs -mkdir -p path4.查看指定目录下内容 hadoop fs -ls [-h] [-R] path hadoop dfs -ls [-h] [-R] ptahpath 指定…...
代码随想录二刷day11
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、力扣20. 有效的括号二、力扣1047. 删除字符串中的所有相邻重复项三、力扣150. 逆波兰表达式求值 前言 一、力扣20. 有效的括号 class Solution {public bo…...
系统架构技能之设计模式-工厂模式
一、开篇 本文主要是讲述设计模式中最经典的创建型模式-工厂模式,本文将会从以下几点对工厂模式进行阐述。 本文将会从上面的四个方面进行详细的讲解和说明,当然会的朋友可以之处我的不足之处,不会的朋友也请我们能够相互学习讨论。 二、摘…...
Docker的基本组成和安装
Docker的基本组成 镜像(image): docker镜像就好比是一个模板,可以通过这个模板来创建容器服务,tomcat镜像 > run > tomcat01容器(提供服务) 通过这个镜像可以创建多个容器(最…...
【python爬虫】15.Scrapy框架实战(热门职位爬取)
文章目录 前言明确目标分析过程企业排行榜的公司信息公司详情页面的招聘信息 代码实现创建项目定义item 创建和编写爬虫文件存储文件修改设置 代码实操总结 前言 上一关,我们学习了Scrapy框架,知道了Scrapy爬虫公司的结构和工作原理。 在Scrapy爬虫公司…...
Apinto 网关 V0.14 版本发布,6 大插件更新!
大家好! 距离上次更新已经过去一段时间了,这段日子里我们一直在酝酿新的功能,本次的迭代将给大家带来 6 大插件的更新~一起来看看有哪些变化吧! 新特性 1. 新增 额外参数v2 插件,支持对转发参数进行加密、拼接等操作…...
突破销售瓶颈:亚马逊卖家如何借力TikTok网红营销?
随着社交媒体的崛起,营销方式也在不断变革。TikTok作为一款风靡全球的短视频平台,吸引了数以亿计的用户,成为了品牌宣传和销售的新热点。对于亚马逊卖家而言,通过合理运用TikTok网红营销策略,可以有效提升产品的曝光度…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
EEG-fNIRS联合成像在跨频率耦合研究中的创新应用
摘要 神经影像技术对医学科学产生了深远的影响,推动了许多神经系统疾病研究的进展并改善了其诊断方法。在此背景下,基于神经血管耦合现象的多模态神经影像方法,通过融合各自优势来提供有关大脑皮层神经活动的互补信息。在这里,本研…...
