c++学习之优先级队列

目录

1.初识优先级队列   

库中的实现

使用优先级队列

2.优先级队列的实现

3.仿函数

利用仿函数实现的优先级队列

迭代器区间构造(建堆)


1.初识优先级队列   

    如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了。这样,我们就引入了优先级队列 这种数据结构。 优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有     

优先队列也是一种抽象数据类型。优先队列中的每个元素都有优先级,而优先级高(或者低)的将会先出队,而优先级相同的则按照其在优先队列中的顺序依次出队。

库中的实现

对于库中的实现,参数来说,可以看到也是给了容器模版(适配器),还给了缺省参数为vector。

其次有一个compare参数(默认下给了缺省参数less的一个对象),实际上还有一个对象greater,这决定了优先级是较大的优先(less),还是较小的优先(greater)。

注意这里与库中的sort的排序顺序是相反的。

       对于接口我们可以看到它与栈的结构很像,其次与堆的结构的结构也很像(我们在数据结构部分知道取堆顶元素),再结合优先级队列的概念,寻找元素的大小,仔细想想:那么实际上优先级队列是一个堆的结构,利用建大堆的方式获取最大的元素等。

实际上对于适配器,我们不仅仅只是数组,我们也可以传双端队列作为适配器也是可以的。

使用优先级队列

简单的使用下,我们可以看到这里在默认的情况下较大的数一个个输出,故默认情况下这里给的是大堆,取堆顶元素便是最大的(删除元素-我们调换堆顶的元素与末尾的元素,向下调整)。

因为是堆的结构,故我们可以知道优先级队列插入删除的时间线复杂度为logN,

void test() 
{priority_queue<int,vector<int> > p;//取大的  大堆//priority_queue<int,vector<int> ,greater<int> > p;//取小的  小堆//入队 p.push(1);p.push(2);p.push(3);p.push(4);p.push(5);p.push(6);//打印并出队 while(!p.empty()){cout<<p.top();p.pop();} } 

通过给出参数的不同,我们可以改变优先级是大或是小。

2.优先级队列的实现

明白了优先级队列的结构之后,我们自己也可以简单实现一下优先级队列。

 这里我们先不知道compare是个啥,我们先实现出默认的大堆结构,也就是大的优先,然后就是给出类型模版和适配器。

//默认实现大的优先级队列 
namespace mypriority_queue
{template<class T,class Container = vector<T> >class priority_queue{public://入优先级队列,本质上就是建大堆 void push(cosnt T& x){//尾插_con.push_back(x); //向上调整 adjust_up(_con.size()-1);//从尾插的位置想上调整 (尾插前size(),故减一) }void adjust_up(int child){size_t parent=(child-1)/2;while(child>0){if(_con[child]>_con[parent]&&child>parent){swap(_con[child],_con[parent]);	child=parent;paren=(parent-1)/2;}					}else{break;}		}//出优先级队列,删除堆顶元素(先交换,在尾删,在向下调整)void pop(){swap(_con[_con.size()-1],_con[0]);_con.pop_back();adjust_down(0);}	void adjust_down(int parent){size_t child=parent*2+1;while(parent<_con.size()){if(child+1<_con.size()&&_con[chid+1]>a[parent]){++child;												}if(_con[chid]>a[parent]){swap(_con[child],_con[parent]);parent=child;child=child*2+1;}}else{break;}}const T& top(){return _con[0];}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;}} 

其中拷贝构造等都不需要我们实现了,系统在调用时会调用我们的容器里的。

3.仿函数

上面已经实现了优先级队列以较大的为优先,那么较小的,我们也可以在实现一个,改变一下向上调整与向上调整的比较符号为小于,就是以小的为优先也就是小堆。

可是我们在用的时候没必要为两份差不多相同的代码搞两个的容器来让我们调用,需要大的用大的,要小的用小的,那么有没有办法可以通过参数的不同的就能直接改变函数成为大堆或小堆,即通过参数不同改变函数。

c++提供了仿函数来实现:

仿函数(functor),就是使一个类的使用看上去像一个函数。其实本质就是类中实现一个重载(),operator(),这个类就有了类似函数的行为,就是一个仿函数类了。

如下:

class Less
{
public:bool operator()(int x,int y){return x>y;}
};
int main()
{Less less;cout<<less(2,3);cout<<less.operator()(2,3);//两者本质一样 return 0;
}

实际上本质上是一个类,类中实现了重载(),简写的时候,本质上是对象调用方法,但看起来像函数调用。

通过仿函数我们就可以实现利用对象调用函数,重载的越多,对象可以调用的也就多了,以这种方式优先级队列可以通过传对象的方法来实现,大的优先级和小的优先级都可以调用

利用仿函数实现的优先级队列

一般使用的时候我们都是将模版与重载()结合起来。

改变传参的仿函数就是改变比较的符号,在通过对象调用:

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;}
};
namespace mypriority_queue
{template<class T,class Container = vector<T> ,class compare=Less<T> >class priority_queue{compare com;public://入优先级队列,本质上就是建大堆 void push(const T& x){//尾插_con.push_back(x); //向上调整 adjust_up(_con.size()-1);//从尾插的位置想上调整 (尾插前size(),故减一) }void adjust_up(int child){int parent=(child-1)/2;while(child>0){if(com(_con[child],_con[parent])&&child>parent){swap(_con[child],_con[parent]);	child=parent;parent=(parent-1)/2;}					}else{break;}		}//出优先级队列,删除堆顶元素(先交换,在尾删,在向下调整)void pop(){swap(_con[_con.size()-1],_con[0]);_con.pop_back();adjust_down(0);}	void adjust_down(int parent){size_t child=parent*2+1;while(parent<_con.size()){if(_con.size>child+1&&com(_con[child+1],a[parent])){++child;												}if(com(_con[child],a[parent])){swap(_con[child],_con[parent]);parent=child;child=child*2+1;}}else{break;}}const T& top(){return _con[0];}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;}} 

对于c++提供的仿函数我们也可以用此替换函数指针,函数指针在实际的应用上比较麻烦,我们可以利用仿函数替换他。

那么现在我们就知道在库中就已经有实现的less和greater,我们可以直接调用库中的。

当然除了库中提供的的less与greater外,我们还可以实现自己所需要的类型的比较,比如对Data类型的数据作比较,我们可以实现自己的仿函数,在通过参数传递用来实现Data类比较。

其次算法库中也提供了许多对于堆的一些判断接口等:

可以看到有堆排序,建堆,出入堆等接口。

迭代器区间构造(建堆)

在原有基础上,添加了另一种初始化的方法,利用迭代器区间来直接完成建堆:

priority_queue(){} //迭代器区间初始化template <class Inputiterator>priority_queue(Inputoriterator first,Inputoriterator last):_con(first,last)//容器提供有迭代器区间初始化 {//建堆:初始化之后--向下调整 for(int i=(_con.size()-2)/2;i>=0;i--){//堆从最后一个parent开始调整 adjust_down(i);}}

因为容器本身具有迭代器区间初始化,我们只需要再次调整即可,此外因为我们自己写入了带有参数的构造函数,那么就需要再补充一个本身的无参构造即可。

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

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

相关文章

怎么通过portainer部署一个vue项目

这篇文章分享一下今天通过docker打包vue项目&#xff0c;并使用打包的镜像在portainer上部署运行&#xff0c;参考了vue-cli和docker的官方文档。 首先&#xff0c;阅读vue-cli关于docker部署的说明 vue-cli关于docker部署的说明https://cli.vuejs.org/guide/deployment.html#…

网络层常见协议——IPV4、IPV6、ARP、ICMP、QoS

目录 1、IPV4 协议 IPV4 地址的组成&#xff1a; IPV4地址的分类&#xff1a; 关于多播和组播&#xff1a; 常见组播地址分类&#xff1a; 特殊的 IPV4 地址&#xff1a; 私有地址和公有地址&#xff1a; 私有地址的范围&#xff1a; 子网划分&#xff1a; 子网掩码&…

操作系统--分页存储管理

一、概念介绍 分页存储&#xff1a;一是分内存地址&#xff0c;二是分逻辑地址。 1.分内存地址 将内存空间分为一个个大小相等的分区。比如&#xff0c;每个分区4KB。 每个分区就是一个“页框”&#xff0c;每个页框有个编号&#xff0c;即“页框号”&#xff0c;“页框号”…

【统计学】Top-down自上而下的角度模型召回率recall,精确率precision,特异性specificity,模型评价

最近在学 logistic regression model&#xff0c;又遇见了几个之前的老面孔。 召回率recall, 精确率precision&#xff0c;特异性spcificity&#xff0c;准确率accuracy&#xff0c;True positive rate&#xff0c;false positive rate等等名词在学习之初遇到的困难在于&#x…

【Java每日一题】— —第十八题:求二维数组中的元素最小值及其索引。(2023.10.02)

&#x1f578;️Hollow&#xff0c;各位小伙伴&#xff0c;今天我们要做的是第十八题。 &#x1f3af;问题&#xff1a; 求二维数组中的元素最小值及其索引。 测试结果如下&#xff1a; &#x1f3af; 答案&#xff1a; int [][]anew int[3][];a[0]new int [3];a[1]new int[5…

全国排名前三的直播公司无锋科技入驻天府蜂巢成都直播产业基地

最近&#xff0c;全国排名前三的直播公司——无锋科技&#xff0c;正式宣布入驻位于成都的天府蜂巢直播产业基地&#xff0c;这一消息引起了业内人士的高度关注。成都直播产业基地一直是中国直播产业的重要地标之一&#xff0c;其强大的技术和资源优势为众多直播公司提供了广阔…

postgresql-管理表空间

postgresql-管理表空间 基本概念创建表空间用户授权移动表空间 修改表空间移动表空间位置 删除表空间 基本概念 在 PostgreSQL 中&#xff0c;表空间&#xff08;tablespace&#xff09;表示数据文件的存放目录&#xff0c;这些数据文件代表了数 据库的对象&#xff0c;例如表…

Oracle SQL Developer 中查看表的数据和字段属性、录入数据

在Oracle SQL Developer中&#xff0c;选中一个表时&#xff0c;右侧会列出表的情况&#xff1b;第一个tab是字段的名称、数据类型等属性&#xff1b; 切换到第二个tab&#xff0c;显示表的数据&#xff1b; 这和sql server management studio不一样的&#xff1b; 看一下部门…

常用的分布式ID解决方案原理解析

目录 前言 一&#xff1a;分布式ID的使用场景 二&#xff1a;分布式ID设计的技术指标 三&#xff1a;常见的分布式ID生成策略 3.1 UUID 3.2 数据库生成 3.3 数据库的多主模式 3.4 号段模式 3.5 雪花算法 前言 分布式ID的生成是分布式系统中非常核心的基础性模块&#…

【C语言】宏定义

&#x1f6a9; WRITE IN FRONT&#x1f6a9; &#x1f50e; 介绍&#xff1a;"謓泽"正在路上朝着"攻城狮"方向"前进四"&#x1f50e;&#x1f3c5; 荣誉&#xff1a;2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2222年获评百大博…

Docker下如何构建包含延迟插件的RabbitMQ镜像

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

OpenGLES:绘制一个彩色、旋转的3D圆柱

一.概述 上一篇博文讲解了怎么绘制一个彩色旋转的立方体 这一篇讲解怎么绘制一个彩色旋转的圆柱 圆柱的顶点创建主要基于2D圆进行扩展&#xff0c;与立方体没有相似之处 圆柱绘制的关键点就是将圆柱拆解成&#xff1a;两个Z坐标不为0的圆 一个长方形的圆柱面 绘制2D圆的…

基于Java的老年人体检管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

SNERT预备队招新CTF体验赛-Web(SWCTF)

目录 1、F12 2、robots 3、game1-喂青蛙 4、game 2 - flap bird 5、game 3 - Clash 6、Get&Post 7、sql &#xff08;1&#xff09;手工注入 &#xff08;2&#xff09;工具注入 8、命令执行漏洞 9、文件上传漏洞 10、文件泄露 11、php反序列化漏洞 12、PHP绕…

数据结构之双链表

双链表 1.复杂方法的图分析2.My_LinkedList代码3.接口MY_lIST4.测试类 1.复杂方法的图分析 2.My_LinkedList代码 package My_liNKEDlIST;public class My_LinkedList implements MY_lIST{static class ListNode{public int val;public ListNode prev;public ListNode next;pub…

Git使用【下】

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析&#xff08;3&#xff09; 目录 &#x1f449;&#x1f3fb;标签管理理解标签标签运用 …

SSM - Springboot - MyBatis-Plus 全栈体系(十七)

第三章 MyBatis 五、MyBatis 高级扩展 1. mapper 批量映射优化 1.1 需求 Mapper 配置文件很多时&#xff0c;在全局配置文件中一个一个注册太麻烦&#xff0c;希望有一个办法能够一劳永逸。 1.2 配置方式 Mybatis 允许在指定 Mapper 映射文件时&#xff0c;只指定其所在的…

函数、函数的傅里叶级数展开、傅里叶级数的和函数之间的关系

1.函数、函数的傅里叶级数展开、傅里叶级数的和函数之间的关系 1.1 傅里叶级数中的系数公式推导 我们先来推导一下傅里叶级数中的系数公式&#xff0c;其实笔者已经写过一篇相关笔记&#xff0c;详见&#xff1a;为什么要把一个函数分解成三角函数?(傅利叶级数) f ( x )…

用AI原生向量数据库Milvus Cloud 搭建一个 AI 聊天机器人

搭建聊天机器人 一切准备就绪后,就可以搭建聊天机器人了。 文档存储 机器人需要存储文档块以及使用 Towhee 提取出的文档块向量。在这个步骤中,我们需要用到 Milvus。 安装轻量版 Milvus Lite,使用以下命令运行 Milvus 服务器: (chatbot_venv) [egoebelbecker@ares milvus_…

Python中匹配模糊的字符串

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 如何使用thefuzz 库&#xff0c;它允许我们在python中进行模糊字符串匹配。 此外&#xff0c;我们将学习如何使用process 模块&#xff0c;该模块允许我们在模糊…