STL-priority_queue的使用及其模拟实现
优先级队列(priority_queue)默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中的元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。
注意: 默认情况下priority_queue是大堆。
priority_queue的使用

priority_queue的构造函数

模板参数 Compare
在 std::priority_queue 类中,通过模板参数 Compare 来指定用于比较元素的函数对象,从而影响堆的排序方式。Compare 是一个仿函数,它定义了元素之间的比较方式。根据不同的 Compare,优先队列可以变成大堆(最大堆)或小堆(最小堆)。
默认的 std::less<T>(大堆):
std::less 是一个函数对象,它重载了 operator(),用于比较两个元素。它返回一个布尔值,表示是否第一个参数小于第二个参数。在默认情况下,如果不提供 Compare 参数,优先队列使用 std::less 作为比较函数对象,即大堆。这意味着在大堆中,父节点的值总是大于或等于子节点的值。
std::greater<T>(小堆):
std::greater<T> 是另一个函数对象,它重载了 operator(),用于比较两个元素。与 std::less<T> 不同,std::greater<T> 返回一个布尔值,表示第一个参数是否大于第二个参数。如果你将 std::greater<T> 传递给 priority_queue,它将会构造一个小堆。在小堆中,父节点的值总是小于或等于子节点的值。
仿函数
仿函数(Functor)是一种重载了函数调用操作符 operator() 的类对象,使得该对象可以像函数一样被调用。它实际上是一种函数对象,它可以具有自己的成员变量和操作,同时可以在使用上类似于普通函数。
使用仿函数的主要优点之一是可以将函数的行为和状态封装在对象中,从而使代码更具有可读性和可维护性。仿函数可以用于各种情况,包括标准算法、STL容器和其他需要函数式操作的地方。
例如:
// 仿函数/函数对象
template<class T>
class Less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};

empty():检查优先队列是否为空
size():用于获取优先队列中元素的数量
top():获取优先队列的顶部元素(最大或最小元素,取决于堆的类型),但不改变队列的内容
push():用于将新元素添加到优先队列中
emplace():在优先队列中插入一个新元素
pop():将优先队列的顶部元素移除,同时会重新调整堆以维持堆的性质
swap(): 用于交换调用对象和传递的参数 x 之间的内容,将两个优先队列的内容互换,但不会改变它们的比较函数或其他属性
模拟实现priority_queue
// Compare进行比较的仿函数 less->大堆
template<class T>
class Less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
bool operator<(const Date& d)const
{
return (_year < d._year) ||
(_year == d._year && _month < d._month) ||
(_year == d._year && _month == d._month && _day < d._day);
}
bool operator>(const Date& d)const
{
return (_year > d._year) ||
(_year == d._year && _month > d._month) ||
(_year == d._year && _month == d._month && _day > d._day);
}
friend ostream& operator<<(ostream& _cout, const Date& d)
{
_cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
private:
int _year;
int _month;
int _day;
};
//类模板特化
template<>
struct Less<Date*>
{
bool operator()(const Date* x, const Date* y)
{
return *x < *y;
}
};
// Compare进行比较的仿函数 greater->小堆
template<class T>
class Greater
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
template<class T, class Container = vector<T>, class Compare = Less<T>>
class priority_queue
{
public:
priority_queue()
{}
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
:_con(first, last)
{
// ½¨¶Ñ
for (int i = (_con.size() - 2) / 2; i >= 0; --i)
{
adjust_down(i);
}
}
void adjust_up(int child)
{
Compare com;
int parent = (child - 1) / 2;
while (child > 0)
{
//有名对象
if (com(_con[parent], _con[child]))
//匿名对象
//if (Compare()(_con[parent], _con[child]))
//if (_con[parent] < _con[child])
{
swap(_con[child], _con[parent]);
child = parent;
parent = (child - 1) / 2;
}
else
{
break;
}
}
}
void adjust_down(int parent)
{
Compare com;
size_t child = parent * 2 + 1;
while (child < _con.size())
{
//if (child + 1 < _con.size()
// //&& _con[child] < _con[child + 1])
if (child + 1 < _con.size()
&& com(_con[child], _con[child + 1]))
{
++child;
}
//if (_con[parent] < _con[child])
if (com(_con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void push(const T& x)
{
_con.push_back(x);
adjust_up(_con.size() - 1);
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
adjust_down(0);
}
const T& top()
{
return _con[0];
}
bool empty()
{
return _con.empty();
}
size_t size()
{
return _con.size();
}
private:
Container _con;
};
class PDateLess {
public:
bool operator()(const Date* p1, const Date* p2) {
return *p1 < *p2;
}
};
class PDateGreater{
public:
bool operator()(const Date* p1, const Date* p2) {
return *p1 > *p2;
}
};
void test_priority_queue() {
priority_queue<int> pq;
pq.push(1);
pq.push(2);
pq.push(3);
pq.push(4);
pq.push(1);
while (!pq.empty()) {
cout << pq.top() << " ";
pq.pop();
}
cout << endl;
}
void test_priority_queue2()
{
// 大堆,需要用户在自定义类型中提供<的重载
priority_queue<Date,vector<Date>,Less<Date>> q1;
q1.push(Date(2018, 10, 29));
q1.push(Date(2018, 10, 28));
q1.push(Date(2018, 10, 30));
cout << q1.top() << endl;
priority_queue<Date*, vector<Date*>> q3;
//priority_queue<Date*, vector<Date*>,PDateLess> q3;
q3.push(new Date(2018, 10, 29));
q3.push(new Date(2018, 10, 28));
q3.push(new Date(2018, 10, 30));
cout << *(q3.top()) << endl;
// 如果要创建小堆,需要用户提供>的重载
priority_queue<Date, vector<Date>, Greater<Date>> q2;
q2.push(Date(2018, 10, 29));
q2.push(Date(2018, 10, 28));
q2.push(Date(2018, 10, 30));
cout << q2.top() << endl;
}
成员函数的模拟实现
模板类 priority_queue:
这是一个模板类,它代表了一个优先队列的实现。它接受三个模板参数:T(元素类型),Container(底层容器类型,默认为 std::vector<T>),和 Compare(用于比较元素的仿函数,默认为 std::less<T>)
Compare 是一个模板参数,用于进行元素的比较。它是一个仿函数,可以是 std::less<T>(默认)或 std::greater<T>,具体取决于用户提供的优先队列类型。Compare 仿函数用于确定在堆中的元素排序方式,从而决定了是最大堆还是最小堆。在 priority_queue 类的各个成员函数中,通过调用 Compare 仿函数来进行元素的比较,从而实现了插入和调整堆的操作。
构造函数 priority_queue():
这是一个默认构造函数,不需要使用 Compare 仿函数进行比较。
构造函数模板 priority_queue(InputIterator first, InputIterator last):
在构造函数内部,使用 Compare 仿函数来执行比较操作,以确定元素的顺序。在添加元素后,通过调用 adjust_down 函数来构建堆。
成员函数 adjust_up(size_t child):
在上浮操作中,使用 Compare 仿函数执行比较,以确定是否需要交换父子节点的位置,从而保持堆的性质。
成员函数 push(const T& x):
在插入操作中,首先将新元素添加到底层容器 _con,然后通过调用 adjust_up 函数来执行上浮操作,保证新元素位于合适的位置。
成员函数 adjust_down(size_t parent):
在下沉操作中,使用 Compare 仿函数执行比较,以确定是否需要交换父子节点的位置,从而保持堆的性质。
成员函数 pop():
在删除操作中,首先将顶部元素与底层容器的最后一个元素交换,然后通过调用 adjust_down 函数来执行下沉操作,保证堆的性质。
成员函数 const T& top():
通过返回 _con[0],获取优先队列的顶部元素。
相关文章:
STL-priority_queue的使用及其模拟实现
优先级队列(priority_queue)默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中的元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。 注意࿱…...
pycharm连接阿里云服务器过程记录
因为不想用自己的电脑安装anaconda环境,所以去查了一下怎么用服务器跑代码,试着用pycharm连接阿里云服务器,参考了很多博客,自己简单配置了一下,记录一下目前完成的流程. 主要是:阿里云服务器的远程登录和安装anaconda,以及怎么用pycharm连接阿里云服务器上的解释器. 小白刚开始…...
移动硬盘未格式化数据恢复及预防策略
随着数字化时代的到来,移动硬盘作为数据存储的重要载体,被广泛应用于个人和企业中。然而,当移动硬盘遭遇“未格式化”的困境时,其中的数据便岌岌可危。本文将深入探讨移动硬盘未格式化的现象、原因、数据恢复方案以及预防措施&…...
MySQL数据库入门之视图、存储过程、触发器
一、视图: 1.1、视图是什么?怎么理解? 视图是从数据库的基本表(或者视图)导出的虚表(数据库只放定义,它不实际存储数据,而是根据用户定义的SQL查询动态生成的结果集,具…...
Kafka原生API使用Java代码-生产者-分区策略-默认分区策略轮询分区策略
文章目录 1、代码演示1.1、pom.xml1.2、KafkaProducerPartitioningStrategy.java1.2.1、ProducerConfig.LINGER_MS_CONFIG取 0 值得情况,不轮询1.2.2、ProducerConfig.LINGER_MS_CONFIG取 0 值得情况,轮询1.2.3、ProducerConfig.LINGER_MS_CONFIG取 1000…...
网页中的音视频裁剪拼接合并
一、需求描述 项目中有一个配音需求: 1)首先,前台会拿到一个英语视频,视频的内容是A和B用英语交流; 2)然后,用户可以选择为某一个角色配音,假如选择为A配音,那么视频在播…...
【入门】使用sklearn实现的KNN算法:鸢尾花数据集分类预测
目录 前言 第一步:安装和导入sklean模块 第二步:获取数据 第二步:分割出训练集和测试集 第三步:训练模型 第四步:测试结果 总结 前言 本文将介绍如何利用K最近邻(KNN)算法对经典的鸢尾花数…...
nss做题
[NCTF 2018]签到题 1.f12在index.php中找到flag [NSSCTF 2022 Spring Recruit]ezgame 1.在js源码中就有flag [UUCTF 2022 新生赛]websign 1.打开环境后发现ctrlu和右键,f12都被禁用了。两种方法,第一种:禁用js;第二中提前打开…...
第18章:JDK8-17新特性
1. 新特性概述 > 角度1:新的语法规则 (多关注)比如:lambda表达式、enum、annotation、自动拆箱装箱、接口中的默认方法和静态方法、switch表达式、record等> 角度2:增加、过时、删除API比如:新的日期…...
哈希表练习题(2024/5/29)
1有效的字母异位词 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。 注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输…...
java —— 连接 MySQL 操作
MySQL 是独立于 java 之外的数据库,二者之间建立连接需要提前引入 mysql-connector-java 的 jar 包。 一、引入方法: ① 在项目中新建一个 Folder(即文件夹),该文件夹通常命名为 lib,意思是存放项目所依赖…...
从 0 开始实现一个博客系统 (SSM 项目)
相关技术 Spring Spring Boot Spring MVC MyBatis Html Css JS pom 文件我就不放出来了, 之前用的 jdk8 做的, MySQL 用的 5.7, 都有点老了, 你们自己看着配版本就好 实现功能 用户注册 - 密码加盐加密 (md5 加密)前后端用户信息存储 - 令牌技术用户登录 - (使用 拦截…...
C++标准模板(STL)- C 内存管理库 - 分配并清零内存 (std::calloc)
C 内存管理库 分配并清零内存 std::calloc void* calloc( std::size_t num, std::size_t size ); 分配 num 个大小为 size 的对象的数组,并初始化所有位为零。 若分配成功,则返回指向为任何对象类型适当对齐的,被分配内存块最低…...
嵌入式开发面试问题总结(持续更新)
面试问题总结 c/c 封装、继承和多态 封装:将属性和方法封装起来,并加以权限区分。继承:子类继承父类的特征和行为,复用了从基类复制而来的数据成员和成员函数(基类私有成员无法被访问),其中构…...
意外发现openGauss兼容Oracle的几个条件表达式
意外发现openGauss兼容Oracle的几个条件表达式 最近工作中发现openGauss在兼容oracle模式下,可以兼容常用的两个表达式,因此就随手测试了一下。 查看数据库版本 [ommopenGauss ~]$ gsql -r gsql ((openGauss 6.0.0-RC1 build ed7f8e37) compiled at 2…...
使用Keepalived提高吞吐量和负载均衡ip_hash.
一 . Nginx使用Keepalived提高吞吐量案例 Keepalived[表示把连接保持一定长连接数来提高吞吐量] 1.1没有使用keepalived参数 upstream tomcats {server 192.168.28.102:8080; } server {listen 88;server_name www.tomcats.com;location / {proxy_pass http://to…...
网络故障与排除(一)
一、Router-ID冲突导致OSPF路由环路 路由器收到相同Router-ID的两台设备发送的LSA,所以查看路由表看到的OSPF缺省路由信息就会不断变动。而当C1的缺省路由从C2中学到,C2的缺省路由又从C1中学到时,就形成了路由环路,因此出现路由不…...
C++之运算符重载
1、运算符重载 //Complex.h #ifndef _COMPLEX_H_ #define _COMPLEX_H_class Complex { public:Complex(int real_, int imag_);Complex();~Complex();Complex& Add(const Complex& other); void Display() const;Complex operator(const Complex& other);privat…...
使用springdoc-openapi-starter-webmvc-ui后访问swagger-ui/index.html 报错404
按照官网说明,引入 springdoc-openapi-starter-webmvc-ui后应该就可以直接访问swagger-ui.html或者swagger-ui/index.html就可以出现swagger页面了,但是我引入后,访问提示报错404. 在我的项目中,有其他依赖间接引入了org.webjars…...
深入理解计算机系统 家庭作业4.52
练习题4.3 p.254 \sim\seq\seq-full.hcl文件内已经说的很清楚了哪些不能更改,哪些是题目要求更改的控制逻辑块. 依据家庭作业4.51的答案,在seq-full.hcl文件内更改对应的HCL描述即可 以下答案注释了#changed的就是更改部分 #/* $begin seq-all-hcl */ ######################…...
开源AI应用构建平台Casibase:从架构设计到生产部署全解析
1. 项目概述:一个开源的AI应用构建平台最近在折腾AI应用开发的朋友,估计都绕不开一个核心痛点:想法很多,但落地太难。从模型选型、API对接、到前端交互、数据管理,每一个环节都够喝一壶。特别是当你想把多个模型、多种…...
nRF52840开发板移植CircuitPython实战:从编译到蓝牙应用
1. 项目概述与核心价值 如果你手头有一块基于 Nordic nRF52840 芯片的开发板,比如官方的 nRF52840-DK 或者 Particle 的 Argon/Xenon,并且厌倦了在 C 语言和复杂的 SDK 中挣扎,想用 Python 的简洁语法快速实现一个蓝牙传感器节点或者物联网设…...
LaTeX-PPT:3分钟掌握PowerPoint专业公式编辑的神器
LaTeX-PPT:3分钟掌握PowerPoint专业公式编辑的神器 【免费下载链接】latex-ppt Use LaTeX in PowerPoint 项目地址: https://gitcode.com/gh_mirrors/la/latex-ppt 还在为PowerPoint中编辑复杂数学公式而头疼吗?LaTeX-PPT这款开源插件彻底改变了游…...
3D模型格式转换终极方案:用stltostp轻松实现STL到STEP的专业转换
3D模型格式转换终极方案:用stltostp轻松实现STL到STEP的专业转换 【免费下载链接】stltostp Convert stl files to STEP brep files 项目地址: https://gitcode.com/gh_mirrors/st/stltostp 你是否曾遇到这样的困境:3D打印的STL模型无法在专业CAD…...
Claude API预算与性能优化实战:四层策略降本增效
1. 项目概述:一个为Claude设计的预算与性能优化技能 最近在折腾Claude API的时候,发现了一个挺有意思的开源项目,叫 budget_and_performance_optimization_claude_skill 。简单来说,这是一个专门为Claude(特别是Clau…...
DevChat:无缝集成IDE的开源AI编程助手,提升开发效率
1. 项目概述:一个真正融入工作流的AI编程伙伴如果你和我一样,每天大部分时间都花在代码编辑器里,那你肯定也经历过这样的场景:想重构一段代码,却卡在命名上;写一个复杂的函数,需要反复查阅文档&…...
RT-Thread Studio实战:搞定DS18B20温度读取的时序坑(附逻辑分析仪调试实录)
RT-Thread Studio实战:DS18B20温度读取的时序调试与逻辑分析仪应用 嵌入式开发中,单总线器件因其简洁的硬件连接而广受欢迎,但恰恰是这种"简单"往往隐藏着最棘手的调试难题。当你在RT-Thread环境下使用DS18B20温度传感器࿰…...
如何使用AI大模型进行报表合并?一句话搞定复制粘贴
每个月底,财务小张都要做一件事:把1月到12月的销售明细表合成年报。12个Excel文件,每个文件30多列,字段名倒是一致,但数据量加起来几十万行。她的老办法是打开所有文件,逐个复制粘贴到一个新表里࿰…...
Windows: 深入剖析pip install SSLError与SSL模块缺失的根源及系统级修复
1. Windows下pip install SSLError的典型表现 最近在Windows系统上用pip安装Python包时,不少朋友都遇到了这样的报错信息:"Cant connect to HTTPS URL because the SSL module is not available"。这个错误通常会出现在使用清华源、阿里云源等…...
OpenClaw开源安全平台:模块化架构、插件化设计与企业级自动化安全运营实践
1. 项目概述:从开源安全工具到企业级安全基线的构建最近在梳理内部安全工具链时,又仔细研究了一下AtlasPA/openclaw-security这个项目。这不仅仅是一个简单的漏洞扫描器或者安全脚本集合,它更像是一个试图将安全左移理念、自动化响应和资产安…...
