c++中priority_queue的应用及模拟实现

1.介绍

priority_queue 是一种数据结构,它允许你以特定的顺序存储和访问元素。在 C++ 标准模板库(STL)中,priority_queue 是一个基于容器适配器的类模板,它默认使用 std::vector 作为底层容器,并且默认使用最大堆来存储元素。priority_queue 中的元素按照优先级顺序排列。默认情况下,优先级最高的元素(即值最大的元素)位于队列的顶部。访问时,只能访问优先级最高的元素(即队列顶部的元素),不能直接访问其他元素。

2.代码体验

测试代码:


#include<vector>
#include<queue>	
#include<iostream>
using namespace std;
int main()
{priority_queue<int> pq;pq.push(20);pq.push(5);pq.push(60);pq.push(80);pq.push(3);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;return 0;
}

运行结果如下:

结果证明,元素确实是按大根堆的形式存储的!

3.自定义比较函数

priority_queue除了直接用于排序元素之外,还能用于自定义比较函数,来改变元素的优先级顺序例如,如果你想让优先队列按照元素的某个属性排序,可以定义一个比较函数

代码示例:

class date
{friend ostream& operator<<(ostream& _cout, const date& d);
public:date(int year=2025,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);}
private:int _year;int _month;int _day;
};
ostream& operator<<(ostream& _cout, const date& d)
{_cout << d._year << " " << d._month << " " << d._day;return _cout;
}int main()
{priority_queue<date, vector<date>, greater<date>> q1;//解释一下这里为什么要写三个参数,而之前的应用为什么写一个参数就可://这是由于priority_queue的模板就是这样给的,(详见下方图片),由于我们要进行//日期的某种排序,需要把第三个参数写上,而c++规定,你要写第三个参数 前面的第二个就必须写//所以我们第二个参数要写上!q1.push(date(2025, 1, 27));q1.push(date(2024, 10, 6));q1.push(date(2025, 5, 8));while (!q1.empty()){cout<< q1.top()<<endl;q1.pop();}return 0;
}

 

运行结果如下:

那个比较函数我们也可以自己来写,也支持的!

class date
{friend ostream& operator<<(ostream& _cout, const date& d);
public:date(int year=2025,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);}
private:int _year;int _month;int _day;
};
ostream& operator<<(ostream& _cout, const date& d)
{_cout << d._year << " " << d._month << " " << d._day;return _cout;
}
int main()
{priority_queue<date, vector<date>> q2;q2.push( date(2025, 1, 27));q2.push( date(2024, 10, 6));q2.push( date(2025, 5, 8));while (!q2.empty()){cout << q2.top() << endl;q2.pop();}return 0;
}

结果如下:

 

我们也可以写一个比较函数来进行比较

比较函数参数:

struct lessdate                          //自定义一个比较函数
{bool operator()(date* p1, date* p2){return *p1 < *p2;}
};

main函数也要变一下:

​
int main()
{priority_queue<date*, vector<date*>, lessdate> q2;q2.push(new date(2025, 1, 27));q2.push(new date(2024, 10, 6));q2.push(new date(2025, 5, 8));while (!q2.empty()){cout << *q2.top() << endl;q2.pop();}return 0;
}​

解释一下这里为什么要new一下,我们的q2是指针, 存储的是指针而不是对象,通过创建一个对象,并将其地址推入q2中,所以要new一下,此外,我们还要加一个比较函数,如果不加直接比的话,就是按照地址的大小来确定输出了,而与输入内容的大小无关了!

注:若比较函数参数不是指针,而是date p1,date p2,那main函数就不需要new date了! 

4.模拟实现priority_queue

 由于其默认使用最大堆来存储元素,因此我们在模拟实现时2,务必要涉及到堆的相关算法,如向上调整算法以及向下调整算法,如有遗忘可以找我之前的博客看一下,在本篇我也会略作讲解

1)基本框架:

#include<vector>
namespace rens
{template<class T>class less{public:bool operator()(const T& x, const T& y){return x < y;}};template<class T>class greater{public:bool operator()(const T& x, const T& y){return x > y;}};template<class T,class container ,class compare>class priority_queue{public:private:container _con;};
}

插入数据:和二叉树,堆一样,先将插入的数据放在最下面的叶结点,在逐步向上调整,以达到最大堆的结构 

删除数据:不要直接将最上面的删去,这样会造成这棵树“辈分混乱、群龙无首”,应先将最上面的数与最后一个数据交换,在向下调整,调整完毕后,删去最后一个数据

整体代码实现:

#include<vector>
#include <iostream>
namespace rens
{template<class T>class less{public:bool operator()(const T& x, const T& y){return x < y;}};template<class T>class greater{public:bool operator()(const T& x, const T& y){return x > y;}};template<class T,class container=std::vector<T> ,class compare=less<T>>class priority_queue{public:void adjust_up(size_t child){compare com;size_t parent = (child - 1) / 2;while (child > 0){if (com(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);          //我们要排大堆,大的往上走child = parent;parent = (child - 1) / 2;}else {break;}}}void push(const T& x){_con.push_back(x);adjust_up(_con.size() - 1);}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 (com(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);}T&  top(){return _con[0];}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:container _con;};
}

代码测试:

#include"priority_queue.h"
#include<iostream>
using namespace std;
//小的优先级高int main()
{cout << "升序" << endl;rens::priority_queue<int, std::vector<int>, rens::greater<int>> pq;pq.push(2);pq.push(5);pq.push(4);pq.push(1);pq.push(50);while (!pq.empty()){std::cout << pq.top()<<" ";pq.pop();}cout << endl << "降序"<<endl;//默认是最大的,因为我们默认参数给的是Lessrens::priority_queue<int, std::vector<int>> pq1;pq1.push(2);pq1.push(5);pq1.push(4);pq1.push(120);pq1.push(1);while (!pq1.empty()){cout << pq1.top()<<" ";pq1.pop();}cout << endl;return 0;
}

5.仿函数

 在 C++ 中,仿函数(Functor)是一种重载了函数调用操作符 operator() 的类或结构体。仿函数可以像函数一样被调用,但它们实际上是对象。仿函数通常用于定义特定行为,它们可以被传递给算法,如 std::sortstd::for_each,以自定义这些算法的行为。

#include<vector>
#include <iostream>
namespace rens
{template<class T>class less{public:bool operator()(const T& x, const T& y){return x < y;}};
}
bool lessfunc(int x, int y)
{return x < y;
}
int main()
{bool (*ptr)(int, int) = lessfunc;rens::less<int> lessfunc;cout << lessfunc(1, 2) << endl;
}

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

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

相关文章

【技术追踪】DiffMIC:用于医学图像分类的双引导扩散网络(MICCAI-2024)

似乎是第一个用于医学图像分类的扩散模型嗷~ 论文&#xff1a;DiffMIC: Dual-Guidance Diffusion Network for Medical Image Classification 代码&#xff1a;https://github.com/scott-yjyang/DiffMIC 0、摘要 扩散概率模型最近在生成式图像建模中表现出了显著的性能&#xf…

Deepseek v3R1 学习笔记

o1 o1 模型在训练过程中混合了多种奖励函数的设计方法&#xff0c;并且尝试从结果监督转向过程监督&#xff0c;在中间过程进行打分 使用的搜索策略&#xff1a;基于树的搜索和基于顺序修改的搜索 R1 R1-Zero 是从基础模型开始&#xff0c;完全由强化学习驱动&#xff0c;不…

技术书籍写作与编辑沟通指南

引言 撰写技术书籍不仅仅是知识的输出过程&#xff0c;更是与编辑团队紧密合作的协同工作。优秀的技术书籍不仅依赖作者深厚的技术背景&#xff0c;还需要精准的表达、流畅的结构以及符合出版要求的编辑润色。因此&#xff0c;如何高效地与编辑沟通&#xff0c;确保书籍质量&a…

DeepSeek+Ollama+AnythingLLM 本地部署完全指南,打造专属知识库

DeepSeekOllamaAnythingLLM 本地部署完全指南&#xff0c;打造专属知识库 1 Ollama 本地化部署DeepSeek R1 Ollama 是一个用于本地运行大语言模型&#xff08;LLMs&#xff09;的开源工具&#xff0c;提供简单的界面和优化的推理引擎 &#xff0c;使用户能够在个人设备上高效…

更换IP属地会影响网络连接速度吗

在数字化时代&#xff0c;网络连接速度对于个人用户和企业来说都至关重要。无论是日常浏览网页、观看视频&#xff0c;还是进行在线办公、游戏娱乐&#xff0c;网络速度都直接影响着我们的体验。而IP属地&#xff0c;作为网络连接中的一个重要元素&#xff0c;其变动是否会引发…

2025 持续防范 GitHub 投毒,通过 Sharp4SuoExplorer 分析 Visual Studio 隐藏文件

在2024年底的网络安全事件中&#xff0c;某提权工具被发现植入后门&#xff0c;攻击者利用 .suo 文件作为隐蔽的攻击方式。由于 .suo 文件是 Visual Studio 项目的隐藏配置文件&#xff0c;通常不为安全研究人员所关注&#xff0c;因此为攻击者提供了潜在的攻击渠道。 初步调查…

每日Attention学习19——Convolutional Multi-Focal Attention

每日Attention学习19——Convolutional Multi-Focal Attention 模块出处 [ICLR 25 Submission] [link] UltraLightUNet: Rethinking U-shaped Network with Multi-kernel Lightweight Convolutions for Medical Image Segmentation 模块名称 Convolutional Multi-Focal Atte…

【自然语言处理(NLP)】NLP实战:IMDB影评情感分析项目

文章目录 介绍IMDB影评情感分析项目数据集项目实现1. 导包2. 加载IMDB数据3. 查看部分数据4. 分词5. 加载数据整合6. 构建模型7. 词嵌入8. 初始化模型和权重9. glove词向量10. 训练和评估11. 预测 个人主页&#xff1a;道友老李 欢迎加入社区&#xff1a;道友老李的学习社区 介…

企业高效管理策略中的关键一环:WorkWin 监控上网时间的软件的效能剖析

在企业日常运营体系中&#xff0c;员工工作效率与网络资源的合理配置&#xff0c;始终是企业管理者重点关注的核心议题。伴随互联网的广泛普及&#xff0c;员工在工作时段内的网络使用行为日益常态化。然而&#xff0c;若缺乏行之有效的上网时间管控机制&#xff0c;极易导致员…

Spring AI 智能体通过 MCP 集成本地文件数据

作者&#xff1a;刘军 Model Context Protocol&#xff08;MCP&#xff09;简介 模型上下文协议&#xff08;即 Model Context Protocol&#xff0c;MCP&#xff09; [ 1] 是一个开放协议&#xff0c;它规范了应用程序如何向大型语言模型&#xff08;LLM&#xff09;提供上下…

DIY Shell:探秘进程构建与命令解析的核心原理

个人主页&#xff1a;chian-ocean 文章专栏-Linux 前言&#xff1a; Shell&#xff08;外壳&#xff09;是一个操作系统的用户界面&#xff0c;它提供了一种方式&#xff0c;使得用户能够与操作系统进行交互。Shell 是用户与操作系统之间的桥梁&#xff0c;允许用户通过命令行…

新春贺岁,共赴AGI之旅

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; 往期精彩文章推荐 季姮教授独家文字版干货 | 面向知识渊博的大语言模型 关于AI TIME AI TIME源起于2019年&#xff0c;旨在发扬科学思辨精神&#xff0c;邀请各界人士对人工智能理论、算法和场景应用的本质问题…

FastAPI之参数传递和参数校验

FastAPI之参数传递 一、请求URL传参1、URL传参2、一个参数名&#xff0c;多个值3、参数校验3.1、默认值设置&#xff0c;和参数接口描述3.2、字符串长度校验3.3、正则表达式校验3.4、数值大小校验 二、请求体传参1、请求体单个传参 一、请求URL传参 1、URL传参 url请求参数是…

Vue Dom截图插件,截图转Base64 html2canvas

安装插件 npm install html2canvas --save插件使用 <template><div style"padding: 10px;"><div ref"imageTofile" class"box">发生什么事了</div><button click"toImage" style"margin: 10px;&quo…

C语言:深入了解指针3

1.回调函数是什么&#xff1f; 基本概念 回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另⼀个函数&#xff0c;当这个指针被⽤来调⽤其所指向的函数 时&#xff0c;被调⽤的函数就是回调函数。回调函数不是由该函…

llama.cpp GGUF 模型格式

llama.cpp GGUF 模型格式 1. Specification1.1. GGUF Naming Convention (命名规则)1.1.1. Validating Above Naming Convention 1.2. File Structure 2. Standardized key-value pairs2.1. General2.1.1. Required2.1.2. General metadata2.1.3. Source metadata 2.2. LLM2.2.…

【C++】STL——vector底层实现

目录 &#x1f495; 1.vector三个核心 &#x1f495;2.begin函数&#xff0c;end函数的实现&#xff08;简单略讲&#xff09; &#x1f495;3.size函数&#xff0c;capacity函数的实现 &#xff08;简单略讲&#xff09; &#x1f495;4.reserve函数实现 &#xff08;细节…

Pinia状态管理

1、为什么要使用Pinia&#xff1f; Pinia 是 Vue 的存储库&#xff0c;它允许跨组件/页面共享状态 Pinia 最初是为了探索 Vuex 的下一次迭代会是什么样子&#xff0c;结合了 Vuex 5 核心团队讨论中的许多想法。最终&#xff0c;我们意识到 Pinia 已经实现了我们在 Vuex 5 中想…

TCP | RFC793

注&#xff1a;本文为 “ RFC793” 相关文章合辑。 RFC793-TCP 中文翻译 编码那些事儿已于 2022-07-14 16:02:16 修改 简介 翻译自&#xff1a; RFC 793 - Transmission Control Protocol https://datatracker.ietf.org/doc/html/rfc793 TCP 是一个高可靠的主机到主机之间…

VMware Workstation Pro安装了Ubuntu 24.04实现与Windows10之间的复制粘贴

windows10安装了VMware Workstation Pro&#xff0c;虚拟机上安装Ubuntu 24.04&#xff0c;想Ubuntu和windows之间实现复制粘贴&#xff0c;便于互相执行下面命令&#xff1a; sudo apt-get autoremove open-vm-tools //卸载已有的工具 sudo apt-get install open-vm-tools …