当前位置: 首页 > news >正文

深入浅出C++ ——priority_queue类深度剖析

文章目录

  • 一、priority_queue类简介
  • 二、priority_queue类常用接口
  • 三、priority_queue类的使用
  • 四、STL中priority_queue类的模拟实现

一、priority_queue类简介

  1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的
  2. 类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。
  3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类元素从特定容器的“尾部”弹出,其称为优先队列的顶部。
  4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:empty() 检测容器是否为空size():返回容器中有效元素个数front():返回容器中第一个元素的引用push_back():在容器尾部插入元素pop_back():删除容器尾部元素
  5. 标准容器类vectordeque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector
  6. 需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数make_heap、push_heap和pop_heap来自动完成此操作。

  以上内容来自:www.cplusplus.com priority_queue类文档的介绍,在STL的学习中,推荐大家看这个文档,对每个类都有详细的介绍。


总结

  优先级队列 (priority_queue) 属于STL中的容器适配器,其底层存储数据的容器默认使用vector,并且使用堆算法使得vector中的元素构造成堆的结构。所以,可以说优先级队列 (priority_queue) 就是堆,默认情况下是大堆在使用时,与queue相同,要引入头文件#include<queue>


二、priority_queue类常用接口

函数名称功能说明
priority_queue()构造一个空的优先级队列
priority_queue(first,last)构造一个空的优先级队列
empty()检测优先级队列是否为空,是返回true,否则返回false
top( )返回优先级队列中最大/最小元素,即堆顶元素
push(X)在优先级队列中插入元素X
pop()删除优先级队列中最大/最小元素,即堆顶元素

priority_queue类常用接口应用

#include<iostream>
#include<queue>
#include<vector>
#include<functional> 
using namespace std;int main()
{vector<int> v = { 10,60,50,20 };//priority_queue<int> pq;priority_queue<int> pq(v.begin(),v.end());pq.push(30);while (!pq.empty()){cout<< pq.top()<<" ";pq.pop();}return 0;
}

三、priority_queue类的使用

切换大小堆

   默认情况下,priority_queue是创建的是大堆,其底层按照小于号比较,默认模板参数为template<class T, class Container =std::vector<T>, class Compare = std::less<T>>;如果要创建小堆,将第三个模板参数换成greater即可,例如priority_queue<int, vector<int>, greater<int>> pq2(v.begin(), v.end());


greater<int>less<T>

  greater和less的头文件为#include <functional>,具体实现见第三节模拟实现部分。 <functional>是C++标准库中的一个头文件,定义了C++标准中多个用于表示函数对象的类模板,包括算法操作、比较操作、逻辑操作;

  建堆时,less<T>是大顶堆,堆元素是从大到小;greater<T>是小顶堆,堆元素是从小到大。

  排序时,less<T>是升序,数组元素是从小到大;greater<T>是降序堆,数组元素是从大到小。


如果priority_queue中放自定义类型的数据,需要在自定义类型中提供> 或者< 的重载

class Date
{
public:Date(int year = 2023, 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;
};void TestPriorityQueue()
{// 大堆,需要用户在自定义类型中提供<的重载priority_queue<Date> q1;q1.push(Date(2023, 1, 2));q1.push(Date(2023, 1, 3));q1.push(Date(2023, 1, 4));cout << q1.top() << endl;// 如果要创建小堆,需要用户提供>的重载priority_queue<Date, vector<Date>, greater<Date>> q2;q2.push(Date(2023, 1, 2));q2.push(Date(2023, 1, 3));q2.push(Date(2023, 1, 4));cout << q2.top() << endl;
}

四、STL中priority_queue类的模拟实现

#pragma once
#include<vector>namespace MyPriority_queue
{template<class T>struct less{bool operator()(const T& l, const T& r){return l < r;}};template<class T>struct greater{bool operator()(const T& l, const T& r){return l > r;}};template<class T, class Container =std::vector<T>, class Compare = std::less<T>>class priority_queue{public://typedef typename Container::value_type VT;void AdjustUp(size_t child){Compare com;size_t parent = (child - 1) / 2;while (child > 0){//if (_con[parent] > _con[child])if (com(_con[parent], _con[child])){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}void push(const T& x){_con.push_back(x);AdjustUp(_con.size() - 1);}void AdjustDwon(size_t 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[parent], _con[child]);parent = child;child = parent * 2 + 1;}else{break;}}}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDwon(0);}T top(){return _con[0];}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:Container _con;};
}
http://www.lryc.cn/news/15824.html

相关文章:

  • 117.Android 简单的拖拽列表+防止越界拖动(BaseRecyclerViewAdapterHelper)
  • 什么是Struts2?有哪些优势
  • Ubuntu22.04 安装Mongodb6.X
  • 启动内核,能启动内核但是无法进入内核,始终卡在某一地方,比如 No soundcards found.
  • SQL零基础入门学习(六)
  • 股票、指数、快照、逐笔... 不同行情数据源的实时关联分析应用
  • 华为OD机试真题Python实现【 不含 101 的数】真题+解题思路+代码(20222023)
  • centos7 搭建ELK(elasticsearch、logstash、kibana)
  • 如何写新闻稿?写好新闻稿的技巧与步骤
  • 抖音不想只做“开心果”
  • MATLAB | 如何用MATLAB绘制这样有气泡感的网络图
  • Linux 远程登录
  • SAP中BOM基础数量及组件数量单位比例关系的注意事项
  • 华为OD机试真题Python实现【最大相连男生数】真题+解题思路+代码(20222023)
  • Vue使用ElementUI对表单元素进行自定义校验
  • linux的文件权限介绍
  • 支付系统中的设计模式03:模板方法模式
  • 【黏住用户的不是小红书,而是它背后的那些人】
  • 基于STM32采用CS创世 SD NAND(贴片SD卡)完成FATFS文件系统移植与测试(中篇)
  • 0基础学插画是报班还是自学
  • 【Spring Cloud Alibaba】000-Spring Cloud Alibaba 问题集锦[持续更新]
  • Java使用MD5加盐对密码进行加密处理,附注册和登录加密解密处理
  • vue3组件篇 Select
  • 华为OD机试 - 员工出勤(Python) | 机试题+算法思路+考点+代码解析 【2023】
  • 力扣:27. 移除元素
  • 华为OD机试 - 剩余可用字符集(Python) | 机试题+算法思路+考点+代码解析 【2023】
  • 金三银四丨黑蛋老师带你剖析-安全开发岗
  • isNaN、Number.isNaN、isFinite、Number.isFinite
  • MyBatis分页插件
  • Vue组件间通信的四种方式(函数回调,自定义事件,事件总线,消息订阅与发布)