C++ STL priority_queue

目录

一.认识priority_queue

二. priority_queue的使用

三.仿函数

 1.什么是仿函数

 2.控制大小堆

 3.TopK问题

四.模拟实现priority_queue

 1.priority_queue的主要接口框架

 2.堆的向上调整算法

 3.堆的向下调整算法

 4.仿函数控制大小堆

 五.priority_queue模拟实现整体代码和测试


一.认识priority_queue

priority_queue----reference

1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。
2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。
3. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。
4. 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:

  • empty():检测容器是否为空
  • size():返回容器中有效元素个数
  • front():返回容器中第一个元素的引用
  • push_back():在容器尾部插入元素
  • pop_back():删除容器尾部元素

5. 标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。
6. 需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数make_heap、push_heap和pop_heap来自动完成此操作。

二. priority_queue的使用

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

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

测试:

#include<queue>
#include<iostream>
using namespace std;
int main()
{//够一个空的优先级队列priority_queue<int> pri_q;//插入数据pri_q.push(2);pri_q.push(27);pri_q.push(25);pri_q.push(244);pri_q.push(212);pri_q.push(9);//连续取出堆顶数据打印while (!pri_q.empty()){cout << pri_q.top()<<' ';pri_q.pop();}return 0;
}

 三.仿函数

如果我们像控制优先级队列是大堆排,还是小堆排,就需要我们使用放仿函数去控制。

1.什么是仿函数

首先仿函数是一个类,它重载了括号运算符,在使用的时候,定义出对象,就像函数一样使用。

例如:

//仿函数
template<class T>
struct Add
{int operator()(int e1, int e2){return e1 + e2;}
};int main()
{Add<int> add;cout << add(10, 20) << endl;return 0;
}

 2.控制大小堆

在头文件<functional>中包含了两个仿函数,less和granter。

less是判断小于的仿函数,对应堆排出来是大堆,granter是判断大于的仿函数,对应堆排出来是小堆。

#include<queue>
#include<functional>
#include<iostream>
using namespace std;
int main()
{//小堆priority_queue<int,vector<int>,greater<int>> small_q;//插入数据small_q.push(2);small_q.push(27);small_q.push(25);small_q.push(244);small_q.push(212);small_q.push(9);//连续取出堆顶数据打印while (!small_q.empty()){cout << small_q.top()<<' ';small_q.pop();}cout  << endl;//大堆priority_queue<int, vector<int>, less<int>> big_q;//插入数据big_q.push(2);big_q.push(27);big_q.push(25);big_q.push(244);big_q.push(212);big_q.push(9);//连续取出堆顶数据打印while (!big_q.empty()){cout << big_q.top() << ' ';big_q.pop();}return 0;
}

 3.TopK问题

这个问题我们在数据结构二叉树堆的部分已经详细的分析了,感兴趣的可以去看看:数据结构---二叉树---堆

四.模拟实现priority_queue

1.priority_queue的主要接口框架

template<class T, class Continer = vector<T>>
class Priority_queue
{
public://插入数据void push(const T& val){_con.push_back(val);//向上调整adjust_up(_con.size() - 1);}//删除数据void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();//向下调整adjust_down(0);}//返回栈顶数据const T& top(){return _con[0];}//判断栈是否为空bool empty(){return _con.empty();}private:Continer _con;//适配容器,默认是vector
};

2.堆的向上调整算法

堆的插入需要保证插入以后还是一个堆,所以这里用到了向上调整算法

在数组中就是,插入一个数在数组的尾上,再通过向上调整算法,调整到合适的位置。

在以堆的角度来看(小堆)为例,将新插入的值看作孩子与其父亲位置的值比较,如果比父亲位置的值还要小,那就将该值与父亲位置的值进行交换,交换后将父亲位置当作新的孩子,继续与其父亲位置的值比较,这样一直向上比较并交换,直到父亲位置的值比自己小或该位置已经没有父亲了,调整结束。

    //向上调整算法void adjust_up(size_t child){//1.计算父亲size_t parent = (child - 1) / 2;while (child > 0){//如果孩子比父亲大,就交换,否则就直接推出if (_con[parent]< _con[child]){swap(_con[parent], _con[child]);//交换之后,父亲成为新的孩子,继续算新的父亲,直到没有孩子了child = parent;parent = (child - 1) / 2;}else{break;}}}

3.堆的向下调整算法

向下调整算法(大堆为例):从第一个结点开始,找到其孩子结点中较大的一个与父亲位置进行交换,然后将孩子作为新的父亲,再次比较和交换,直到父亲结点比两个结点的值都大或者已经没有孩子了为止。

    //向下调整void adjust_down(size_t parent){//计算出左孩子size_t child = parent * 2 + 1;while (child < _con.size()){//判断是否有右孩子,右孩子是否比左孩子大if (child + 1 < _con.size() && _con[child]< _con[child + 1]){child++;}//较大的孩子如果比父亲大就交换,否则就直接退出循环if (_con[parent]< _con[child]){swap(_con[child], _con[parent]);}else{break;}//孩子成为新的父亲,继续算出新的孩子parent = child;child = parent * 2 + 1;}}

 4.仿函数控制大小堆

//比较小于的仿函数,控制大堆template<class T>struct less{bool operator()(const T& val1,const T& val2){return val1 < val2;}};//比较大于的仿函数,控制小堆template<class T>struct grater{bool operator()(const T& val1, const T& val2){return val1 > val2;}};template<class T, class Continer = vector<T>,class Compare =less<T>>//默认大堆
class Priority_queue
{
public:Compare com;//插入数据void push(const T& val){_con.push_back(val);//向上调整adjust_up(_con.size() - 1);}//删除数据void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();//向下调整adjust_down(0);}//返回栈顶数据const T& top(){return _con[0];}//判断栈是否为空bool empty(){return _con.empty();}private:Continer _con;//适配容器,默认是vector
};

 五.priority_queue模拟实现整体代码和测试

Queue.hpp:

    template<class T, class Continer = vector<T>,class Compare =less<T>>class Priority_queue{public:Compare com;void push(const T& val){_con.push_back(val);adjust_up(_con.size()-1);}void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);}const T& top(){return _con[0];}size_t size(){return _con.size();}bool empty(){return _con.empty();}private://向上调整算法void adjust_up(size_t child){size_t parent = (child - 1) / 2;while (child > 0){if (com(_con[parent] , _con[child])){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}//向下调整void adjust_down(size_t parent){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])){swap(_con[child], _con[parent]);}else{break;}parent = child;child = parent * 2 + 1;}}private:Continer _con;};
}

main:

#include<iostream>
#include<vector>
#include<list>
using std::vector;
using std::list;
using std::cout;
using std::endl;
using std::swap;#include"Queue.hpp"
using namespace Qikun;int main()
{//小堆Priority_queue<int,std::vector<int>, greater<int>> small_q;//插入数据small_q.push(2);small_q.push(27);small_q.push(25);small_q.push(244);small_q.push(212);small_q.push(9);//连续取出堆顶数据打印std::cout << "小堆:";while (!small_q.empty()){cout << small_q.top()<<' ';small_q.pop();}cout  << endl;//大堆Priority_queue<int, vector<int>, less<int>> big_q;//插入数据big_q.push(2);big_q.push(27);big_q.push(25);big_q.push(244);big_q.push(212);big_q.push(9);//连续取出堆顶数据打印cout << "大堆:";while (!big_q.empty()){cout << big_q.top() << ' ';big_q.pop();}return 0;
}

 

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

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

相关文章

用js快速生成一个简单的css原子库 例如: .mr-18 .pl-18

第三方css原子库的缺点 比如 tailwindcss&#xff0c;有学习成本最开始写的时候效率可能还没有我们自己手写效率高&#xff0c;需要配置&#xff0c;会有原始样式被覆盖的问题&#xff1b;总之就是一个字重 自己搓的优点 学习成本低灵活不会有副作用 <!DOCTYPE html>…

Redis详解

Redis 简介 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的高性能键值对存储数据库&#xff0c;最初由 Salvatore Sanfilippo 开发&#xff0c;它在内存中存储数据&#xff0c;并提供了持久化功能&#xff0c;可以将数据保存到磁盘中&#xff0c;是一种N…

Stephen Wolfram:那么…ChatGPT 在做什么,为什么它有效呢?

So … What Is ChatGPT Doing, and Why Does It Work? 那么…ChatGPT在做什么&#xff0c;为什么它有效呢&#xff1f; The basic concept of ChatGPT is at some level rather simple. Start from a huge sample of human-created text from the web, books, etc. Then train…

阿里云内容审核服务使用(图片审核)

说明&#xff1a;在项目中&#xff0c;我们经常会对用户上传的内容&#xff08;如文字、图片&#xff09;等资源内容进行审核&#xff0c;审核包括两方面&#xff0c;一方面是内容与描述不符&#xff0c;一方面是违反法律法规。本文介绍使用阿里提供的内容审核服务&#xff0c;…

mqttfx连上OneNET生成token时的一大坑,报用户名或密码错误

整个流程如下连接&#xff1a; MQTT.fx和MQTTX 链接ONENET物联网开发平台避坑细节干货。 其中在生成token时&#xff0c;搞了半天在连接后都会报用户名密码错误 最后发现是格式问题&#xff0c;输入所有字符后一定要双击看是否可以全选中&#xff0c;可以全选中说明字符的格式…

第G1周:生成对抗网络(GAN)入门

&#x1f368; 本文为[&#x1f517;365天深度学习训练营]内部限免文章&#xff08;版权归 *K同学啊* 所有&#xff09; &#x1f356; 作者&#xff1a;[K同学啊] 一、理论基础 生成对抗网络&#xff08;Generative Adversarial Networks, GAN&#xff09;是近年来深度学习领域…

adb对安卓app进行抓包(ip连接设备)

adb对安卓app进行抓包&#xff08;ip连接设备&#xff09; 一&#xff0c;首先将安卓设备的开发者模式打开&#xff0c;提示允许adb调试 二&#xff0c;自己的笔记本要和安卓设备在同一个网段下&#xff08;同连一个WiFi就可以了&#xff09; 三&#xff0c;在笔记本上根据i…

【Git】安装以及基本操作

目录 一、初识Git二、 在Linux底下安装Git一&#xff09;centOS二&#xff09;Ubuntu 三、 Git基本操作一&#xff09; 创建本地仓库二&#xff09;配置本地仓库三&#xff09;认识工作区、暂存区、版本库四&#xff09;添加文件五&#xff09;查看.git文件六&#xff09;修改文…

【分布式技术专题】RocketMQ延迟消息实现原理和源码分析

痛点背景 业务场景 假设有这么一个需求&#xff0c;用户下单后如果30分钟未支付&#xff0c;则该订单需要被关闭。你会怎么做&#xff1f; 之前方案 最简单的做法&#xff0c;可以服务端启动个定时器&#xff0c;隔个几秒扫描数据库中待支付的订单&#xff0c;如果(当前时间-订…

RocketMQ双主双从同步集群部署

&#x1f388; 作者&#xff1a;互联网-小啊宇 &#x1f388; 简介&#xff1a; CSDN 运维领域创作者、阿里云专家博主。目前从事 Kubernetes运维相关工作&#xff0c;擅长Linux系统运维、开源监控软件维护、Kubernetes容器技术、CI/CD持续集成、自动化运维、开源软件部署维护…

Java接口压力测试—如何应对并优化Java接口的压力测试

导言 在如今的互联网时代&#xff0c;Java接口压力测试是评估系统性能和可靠性的关键一环。一旦接口不能承受高并发量&#xff0c;用户体验将受到严重影响&#xff0c;甚至可能导致系统崩溃。因此&#xff0c;了解如何进行有效的Java接口压力测试以及如何优化接口性能至关重要…

Linux系统USB摄像头测试程序(二)_读取配置

1、收先安装gtk3&#xff0c;我的测试机器是ubutn16.04&#xff0c;只要执行下面的安装命令就可以了 apt-get install libgtk-3-dev 使用下列命令验证是否安装好gtk3&#xff1a; pkg-config --cflags --libs gtk-3.0 2、显示结果类似如下&#xff1a; -pthre…

这是一篇关于SQL 脚本表间连接join的可视化说明

使用SQL合并两个数据集可以通过JOINS来完成。JOIN是查询的FROM子句中的SQL指令&#xff0c;用于标识要查询的表以及它们应该如何组合。 主键和外键 通常&#xff0c;在关系数据库中&#xff0c;数据被组织到由属性&#xff08;列&#xff09;和记录&#xff08;行&#xff09…

MySQL运维

日志 错误日志 show VARIABLES like %log_error%;使用 tail -f 错误文件路径 可以查看具体错误二进制日志 show variables like %log_bin%;在my.ini文件下的mysqlID下添加 log_binmysql-bin binlog-formatROW重启就开启binlog了 show VARIABLES like %binlog_format%;mys…

i18n 配置vue项目中英文语言包(中英文转化)

一、实现效果 二、下载插件创建文件夹 2.1 下载cookie来存储 npm install --save js-cookienpm i vue-i18n -S 2.2 封装组件多页面应用 2.3 创建配置语言包字段 三、示例代码 3.1 main.js 引用 i18n.js import i18n from ./lang// 实现语言切换:i18n处理element&#xff0c…

屏蔽socket 实例化时,握手阶段报错信息WebSocket connection to ‘***‘ failed

事情起因是这样的&#xff1a; 我们网站是需要socket链接实行实时推送服务&#xff0c;有恶意竞争对手通过抓包或者断网&#xff0c;获取到了我们的socket链接地址&#xff0c;那么他就可以通过java写一个脚本无限链接这个socket地址。形成dos攻击。使socket服务器资源耗尽&…

【运维】linkis安装dss保姆级教程与踩坑实践

文章目录 一. 安装准备二. 创建用户三. 准备安装包四. 修改配置1. 修改config.sh2. 修改db.sh 五、安装和使用1. 执行安装脚本2. 启动服务3. 查看验证是否成功 六. 报错处理报错一&#xff1a;The user is not logged in报错二&#xff1a;dss接口报错报错三&#xff1a;执行没…

算法随笔:图论问题之割点割边

割点 定义 割点的定义&#xff1a;如果一个点被删除之后会导致整个图不再是一个连通图&#xff0c;那么这个顶点就是这个图的割点。举例&#xff1a; 上图中的点2就是一个割点&#xff0c;如果它被删除&#xff0c;则整个图被分为两个连通分量&#xff0c;不再是一个连通图。…

vue3多条件搜索功能

搜索功能在后台管理页面中非常常见&#xff0c;本篇就着重讲一下vue3-admin-element框架中如何实现一个顶部多条件搜索功能 一、首先需要在vue页面的<template></template>中写入对应的结构 <!-- 搜索 --><div style"display: flex; justify-content…

突破大模型 | Alluxio助力AI大模型训练-成功案例(一)

更多详细内容可见《Alluxio助力AI大模型训练制胜宝典》 【案例一&#xff1a;知乎】多云缓存在知乎的探索:从UnionStore到Alluxio 作者&#xff1a;胡梦宇-知乎大数据基础架构开发工程师&#xff08;内容转载自InfoQ&#xff09; 一、背景 随着云原生技术的飞速发展&#xff…