实现优先队列——C++

目录

1.优先队列的类模板

2.仿函数的讲解

3.成员变量

4.构造函数

5。判空,返回size,返回队头

6.插入

7.删除


1.优先队列的类模板

我们先通过模板来进行初步了解

由上图可知,我们的模板里有三个参数,第一个参数自然就是你要存储的数据的类型了;第二个参数是我们的适配器,适配器可以手动更改,但我们这里就用它默认的vector,这就意味着我们的优先队列是由我们的顺序表容器来实现的;第三个参数是我们的仿函数,仿函数是我们这个优先队列的重要知识点,等会我会详细说明。

我先把代码全放出来,这样方便不理解的时候可以看到全部代码来思考。

我提前说明一下,优先队列的本质其实就是vector和堆的性质。

template<class T>class less{public:bool operator()(const T& a, const T& b){return a < b;}};template<class T>class greater{public:bool operator()(const T& a, const T& b){return a > b;}};template<class T,class Container=vector<T>,class comper=less<T>>class priority_queue{public://构造priority_queue(){}//拷贝构造//模板函数//迭代器版template <class InputIterator>priority_queue(InputIterator first, InputIterator last){while (first != last){push(*first);first++;}}//判空bool empty() const{return _con.empty();}//返回sizesize_t size() const{return _con.size();}//返回队头const T& top(){return _con[0];}//插入//向上调整void adjustup(size_t child){size_t parent = (child - 1) / 2;while (child > 0){if (cmp(_con[parent], _con[child])){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}elsebreak;}}void push(const T& x){_con.push_back(x);adjustup(_con.size()-1);}//删除//向下调整void adjustdown(size_t parent){size_t child = parent * 2 + 1;while (child < _con.size()){if (child+1<_con.size() && cmp(_con[child], _con[child+1])){child++;}if (cmp(_con[parent], _con[child])){swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}elsebreak;}}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjustdown(0);}private:Container _con;comper cmp;};

2.仿函数的讲解

仿函数是什么意思呢,我们不妨猜测一下,通过它的名字,仿函数似乎是一个模仿函数的存在,这个猜测其实就是对的。仿函数没有什么门道,它的底层就是进行了一个运算符重载,重载的是(),所以调用的时候感觉像是在调用函数一样。

template<class T>class less{public:bool operator()(const T& a, const T& b){return a < b;}};

我们可以通过上面的代码发现我们的类叫less,里面重载了一个()运算符,使其能达到判断较小值的目的;

template<class T>class greater{public:bool operator()(const T& a, const T& b){return a > b;}};

有了判断较小值,自然就有判断较大值,原理也是跟上面一样。

有了仿函数我们就能更加方便且安全的对自定义类型的数据进行有意义的大小比较。

3.成员变量

private:Container _con;comper cmp;

成员变量我们自然还是设置成私有的,这两个成员变量的类型是不是有一点懵逼?其实是我们的类模板声明的。

template<class T,class Container=vector<T>,class comper=less<T>>

所以我们的第一个成员变量的类型是我们的vector,第二个是我们的仿函数类型的数据。

4.构造函数

//构造priority_queue(){}

其实我们仔细想一想就能明白,我们的优先队列的底层既然是vector和堆,而我们的优先队列存在的意义就像是给vector再加工一下,实现堆的性质和功能,所以我们的优先队列甚至不需要自己实现构造函数,直接让它自动调用vector的就行了。析构函数也是一样的道理,我们既然不需要写构造函数,那么析构函数直接不定义了,调用系统默认的就可以了。

5。判空,返回size,返回队头

//判空bool empty() const{return _con.empty();}//返回sizesize_t size() const{return _con.size();}//返回队头const T& top(){return _con[0];}

这三个功能真的没有什么好解释的,大家一看就能理解,这不都是复用了vector的功能嘛。

6.插入

//插入//向上调整void adjustup(size_t child){size_t parent = (child - 1) / 2;while (child > 0){if (cmp(_con[parent], _con[child])){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}elsebreak;}}void push(const T& x){_con.push_back(x);adjustup(_con.size()-1);}

插入功能就是这个优先队列不同于顺序表的地方之一了,因为是堆的性质,所以我们插入的时候肯定不能单纯的插入,我们要进行向上调整,向上调整的目的就是把我们的vector打造成堆的模样。我们就来讲解一下向上调整

我们这次建的是大堆,大堆是什么意思呢?大堆就是我们的父亲节点要大于我们的孩子节点,所以如果我们的父亲节点小于孩子节点我们就交换父亲节点和孩子节点的值。

仿函数的用法就出现了

cmp(_con[parent], _con[child])

不说的话大家是不是就以为cmp是我们的普通函数了?仿函数的妙用就在这里。

然后我再说明一下,孩子节点和父亲节点是如何来确定的,我们知道顺序表的物理结构也是连续的,下标从0开始,我们的父亲节点只需要*2加1就能找到左孩子,再加一就能找到右孩子,而我们的不管是左孩子还是右孩子都只需要-1再除2就能找到父亲了,这其中的数学原理大家下去画画图,很快就能得出这个结论了。

7.删除

//删除//向下调整void adjustdown(size_t parent){size_t child = parent * 2 + 1;while (child < _con.size()){if (child+1<_con.size() && cmp(_con[child], _con[child+1])){child++;}if (cmp(_con[parent], _con[child])){swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}elsebreak;}}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjustdown(0);}

删除用的就是我们的向下调整了。我们的优先队列的数据是连续的,从头部删除性能肯定不好,所以我们的思路是先把要删除的元素跟最后一个交换,然后删除最后一个元素就能达到我们的效果了,这个时候为了保证我们堆的性质要对首元素进行调整,调整到它该去的位置。

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

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

相关文章

读天才与算法:人脑与AI的数学思维笔记16_音乐图灵测试

1. 艾米 1.1. 人工智能作曲家 1.1.1. 分析机可能会生成任意复杂程度、精细程度的科学的音乐作品 1.1.1.1. 阿达洛夫莱斯 1.1.2. 巴赫的作品是大多数作曲家开始学习创作的起点&#xff0c;也是大多数计算机开始学习作曲的起点…

uniapp 短视频浏览组件(仿抖音、上滑下滑)组件 Ba-VideoSView

简介&#xff08;下载地址&#xff09; Ba-VideoSView 是一款uniapp短视频上划浏览组件&#xff0c;支持无限滑动加载&#xff0c;支持自定义界面&#xff08;功能遮罩&#xff09;,支持点播、直播。 支持无限滑动加载支持自定义界面&#xff08;遮罩&#xff09;支持监听上滑…

第 8 章 机器人平台设计(自学二刷笔记)

重要参考&#xff1a; 课程链接:https://www.bilibili.com/video/BV1Ci4y1L7ZZ 讲义链接:Introduction Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 学习到当前阶段大家对ROS已经有一定的认知了&#xff0c;但是之前的内容更偏理论&#xff0c;尤其是介绍完第6…

KKView远程控制2.0版本发布,TeamViewer面临巨大挑战

KKView远程控制2.0版本发布&#xff0c;TeamViewer面临巨大挑战 近日&#xff0c;备受瞩目的远程控制软件KKView发布了其全新2.0版本&#xff0c;KKView以其独特的创新性和用户友好的设计&#xff0c;为远程办公、远程培训等领域提供了更加高效、便捷的解决方案。 KKView远程…

K8S 哲学 - deployment -- kubectl【create 、 rollout 、edit、scale、set】

kubectl create kubectl rollout kubectl edit kubectl set kubectl scale 1、创建与配置文件解析 2、deploy 滚动更新 &#xff1a;template 里面的内容改变触发滚动更新 编辑该 deploy 的 配置文件 &#xff0c;加入一个 label 不会触发滚动更新 改变 nginx镜…

分布式与一致性协议之Raft算法(一)

Raft算法 概述 Raft算法属于Multi-Paxos算法&#xff0c;它在兰伯特Multi-Paxos思想的基础上做了一些简化和限制&#xff0c;比如日志必须是连续的&#xff0c;只支持领导者(Leader)、跟随者(Follwer)和候选人(Candidate)3种状态。在理解和算法实现上&#xff0c;Raft算法相对…

Python语言零基础入门——文件

目录 一、文件的基本概念 1.文件 2.绝对路径与相对路径 3.打开文件的模式 二、文件的读取 三、文件的追加 四、文件的写入 五、with语句 六、csv文件 1.csv文件的读取 2.csv文件的写入 七、练习题&#xff1a;实现日记本 一、文件的基本概念 1.文件 文件是以计算…

浏览器安装路径位置的查看、指定网址快捷方式的创建

浏览器安装路径位置的查看、指定网址快捷方式的创建 浏览器安装路径位置的查看 法一、属性查看法 右键点击浏览器的桌面图标&#xff0c;选择“属性”&#xff0c;“快捷方式”页中的“目标”框中可见. 以Microsoft Edge浏览器为例&#xff0c;参见下图&#xff1a; 法二、地…

免费开源语音克隆-GPT-SoVITS-WebUI只需 5 秒的声音样本

语音克隆-GPT-SoVITS-WebUI 强大的少样本语音转换与语音合成Web用户界面。 功能&#xff1a; 零样本文本到语音&#xff08;TTS&#xff09;&#xff1a; 输入 5 秒的声音样本&#xff0c;即刻体验文本到语音转换。 少样本 TTS&#xff1a; 仅需 1 分钟的训练数据即可微调模型…

LabVIEW换智能仿真三相电能表研制

LabVIEW换智能仿真三相电能表研制 在当前电力工业飞速发展的背景下&#xff0c;确保电能计量的准确性与公正性变得尤为重要。本文提出了一种基于LabVIEW和单片机技术&#xff0c;具有灵活状态切换功能的智能仿真三相电能表&#xff0c;旨在通过技术创新提高电能计量人员的培训…

基于SpringBoot+Vue的旅游网站系统

初衷 在后台收到很多私信是咨询毕业设计怎么做的&#xff1f;有没有好的毕业设计参考?能感觉到现在的毕业生和当时的我有着同样的问题&#xff0c;但是当时的我没有被骗&#xff0c;因为现在很多人是被骗的&#xff0c;还没有出学校还是社会经验少&#xff0c;容易相信别人。…

项目管理-项目进度管理2/3

项目管理&#xff1a;每天进步一点点~ 活到老&#xff0c;学到老 ヾ(◍∇◍)&#xff89;&#xff9e; 何时学习都不晚&#xff0c;加油 项目进度管理&#xff1a;需掌握 ITTO, 搞懂计算图&#xff0c;问题和解决方案。 项目进度管理6个过程&#xff0c;包括&#xff08;口…

机器学习:深入解析SVM的核心概念【二、对偶问题】

对偶问题 **问题一&#xff1a;什么叫做凸二次优化问题&#xff1f;而且为什么符合凸二次优化问题&#xff1f;**为什么约束条件也是凸的半空间&#xff08;Half-Space&#xff09;凸集&#xff08;Convex Set&#xff09;半空间是凸集的例子SVM 约束定义的半空间总结 **问题二…

nginx的前世今生(二)

书接上回&#xff1a; 上回书说到&#xff0c;nginx的前世今生&#xff0c;这回我们继续说 3.缓冲秘籍&#xff0c;洪流控水 Nginx的缓冲区是其处理数据传输和提高性能的关键设计之一&#xff0c;主要用于暂存和管理进出的数据流&#xff0c;以应对不同组件间速度不匹配的问题…

Dokcer容器分布式搭建LNMP+wordpress论坛

目录 引言 一、架构环境 二、搭建容器 &#xff08;一&#xff09;自定义网络 &#xff08;二&#xff09;搭建nginx容器 1.文件准备 2.查看与编辑文件 3.生成镜像 4.创建容器 &#xff08;三&#xff09;搭建MySQL容器 1.文件准备 2.查看与编辑文件 3.生成镜像 …

基于Unity+Vue通信交互的WebGL项目实践

unity-webgl 是无法直接向vue项目进行通信的&#xff0c;需要一个中间者 jslib 文件 jslib当作中间者&#xff0c;unity与它通信&#xff0c;前端也与它通信&#xff0c;在此基础上三者之间进行了通信对接 看过很多例子&#xff1a;介绍的都不是很详细&#xff0c;不如自己写&…

【银角大王——Django课程——用户表的基本操作】

Django课程——用户表的基本操作 模板的继承用户管理用户列表展示新建用户Django组件原始方法【麻烦&#xff0c;太原始】form组件modelform组件 使用modelsform组件编写添加页面 模板的继承 &#xff08;1&#xff09;先写一个页面模板————这个案例中的模板基本上就是一个…

分布式与一致性协议之CAP和Paxos算法(一)

CAP 理论 如何使用BASE理论 以InfluxDB系统中DATA节点的集群实现为例。DATA节点的核心功能是读和写&#xff0c;所以基本可用是指读和写的基本可用。我们可以通过分片和多副本实现读和写的基本可用。也就是说&#xff0c;将同一业务的数据先分片&#xff0c;再以多份副本的形…

嫦娥六号发射任务圆满成功,开启月球背面采样返回之旅 | 最新快讯

央视新闻5月3日消息&#xff0c;据国家航天局&#xff0c;5月3日17时27分&#xff0c;嫦娥六号探测器由长征五号遥八运载火箭在中国文昌航天发射场成功发射&#xff0c;准确进入地月转移轨道&#xff0c;发射任务取得圆满成功。嫦娥六号探测器开启世界首次月球背面采样返回之旅…

光固化打印--问题记录

平面翘起 原因&#xff1a;角度平&#xff0c;缺支持 解决&#xff1a; 45度角度摆放底部平面起皮 原因&#xff1a;缺少支撑&#xff0c;原始结构支持无法支撑平面。 解决&#xff1a;增加支撑