C++容器适配器与stack,queue,priority_queue(优先级队列)的实现以及仿函数(函数对象)与deque的简单介绍

🎉个人名片:

🐼作者简介:一名乐于分享在学习道路上收获的大二在校生
🙈个人主页🎉:GOTXX
🐼个人WeChat:ILXOXVJE
🐼本文由GOTXX原创,首发CSDN🎉🎉🎉
🐵系列专栏:零基础学习C语言----- 数据结构的学习之路----C++的学习之路
🐓每日一句:如果没有特别幸运,那就请特别努力!🎉🎉🎉 ————————————————

🎉文章简介:

🎉本篇文章将 学习c++容器适配器与stack,queue应用适配器实现 相关知识进行分享!
💕如果您觉得文章不错,期待你的一键三连哦,你的鼓励是我创作动力的源泉,让我们一起加 油,一起奔跑,让我们顶峰相见!!!🎉🎉🎉
——————————————————

一.容器适配器

一.什么是容器适配器

容器适配器是一种设计模式,它通过封装现有的序列容器类,并重定义其成员函数,以提供不同的功能或满足特定的需求。这种适配器类似于电源适配器,它将不兼容的电源(如不同国家的电压标准)转换可用的电源(即适合电器使用的电压),以便用户能够方便地使用各种电器。

在计算机编程中,容器适配器允许程序员使用已经存在的序列容器类(如vector、deque、list等),同时获得预定义的特定功能,如stack实现后进先出(LIFO)存储、queue实现先进先出(FIFO)存储、以及priority_queue实现基于优先级的存储。

容器适配器本质上是容器的一种变体,它利用了其他基础容器模板类中已经实现的成员函数,并在必要时添加或创新自己的成员函数。

如图:
在这里插入图片描述

二.STL中stack,queue在底层中的结构

STL中stack与queue不属于容器,而是容器适配器,他们是基于已经存在的类(容器)上面,对该类(容器)的接口进行了包装,STL中stack和queue默认使用deque;

们可以通过文档发现:
如图:
在这里插入图片描述
在这里插入图片描述

二.相关适配器的介绍及实现

简单的说,这里的适配器的实现,就是在一个类里面,定义一个其他容器的对象A(能支持该适配器B的功能),然后在实现 B 所需要的函数的时候,在函数里面调用 A的成员函数 来实现 B的函数 或则 B函数 的某部分,然而实现B;
可以结合下面的例子看看:

一.stack

一.stack的介绍

stack的文档 link
1. stack是一种容器适配器,具有 后进先出 的特点,是只允许在一端进行删除,插入,提取操作的容器适配器;

2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。

3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:

empty:判空操作
back:获取尾部元素操作
push_back:尾部插入元素操作
pop_back:尾部删除元素操作

4. 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque。

后进先出特点
在这里插入图片描述

相关函数
在这里插入图片描述

二.实现:
  //这里的Cintainer不确定是什么,默认不传我们给的是deque<int>,和库里面一致template<class T, class Container=deque<int>>  //模板参数是传类型class stack{public:stack()         //初始化,会去调用对象_con的构造函数:_con()     //这里_con默认是deque{}void push(const T& x)    //这里成员函数名可以自己随便修改,这里是为了和库里面的一致{_con.push_back(x);    //这里调用的函数必须是对象_con的成员函数,并且名字必须相同}void pop()         {_con.pop_back();   //下面的调用和上面的都类似}T& top(){return _con.back();   //调用_con的取头数据函数}bool empty(){return _con.empty();    //调用_con的判空函数}size_t size(){return _con.size();    //调用_con的size()函数}private:     Container _con;       //声明一个Container对象};

stack的实现完全就是自己什么都不做,全去调用Contaoner的成员函数就可以实现的,下面的queue也是一样;

二.queue

一.queue的介绍

queue文档链接: link

1. 队列是一种容器适配器,专门用于在先进先出(比如现实中取号排队的问题,越早取号的先)中操作,其中从容器一端插入元素,另一端提取元素;

2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。

3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:

empty:检测队列是否为空
size:返回队列中有效元素的个数
front:返回队头元素的引用
back:返回队尾元素的引用
push_back:在队列尾部入队列
pop_front:在队列头部出队列

4. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

先进先出 特点
在这里插入图片描述
函数使用
在这里插入图片描述

二.实现

与stack的实现一样

template<class T,class Container=deque<int>>   //库里面一致,默认是deque<int>
class quque
{
public:quque():_con(){}void push(const T& x){_con.push_back(x);    //调用_con的成员函数}void pop(){_con.pop_front();}T& top(){return _con.front();}size_t size(){return _con.size();}bool empty(){return _con.empty();}
private:Container _con;
};

三.priority_queue

一.priority_queue的介绍

priority_queue文档链接: link

1. 优先队列是一种容器适配器,类似于堆,默认情况下是大堆,即堆顶的元素总是它所包含的元素中最大的;

2. 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。

3. 标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。因为vector支持下标随机访问

4.需要支持随机访问迭代器,以便始终在内部保持堆结构;
支持以下操作:

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

函数使用
在这里插入图片描述

.实现

仿函数的简单介绍

仿函数,就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了;
有了仿函数类过后,再结合模板使用,就可以使一些需要重复使用的代码独立出来,以便下次复用,这样有利于资源的管理(这点可能是它相对于函数最显著的优点了)。

就比如下面我们所需要实现的优先队列,默认的是大堆(如图,库里面是反着的,less是大堆,greater是小堆),当我们想要小堆的时候,就需要用仿函数,这样只需要我们再使用优先级队列时改变传的模板参数即可;
在这里插入图片描述

向上调整与向下调整思想及图解链接: link

template<class T>
class lesser               //定义一个类
{
public:bool operator()(const T& x, const T& y)   //重载operator(){return x < y;                  //小于的比较逻辑}
};
template<class T>                 //定义一个类
class greater
{
public:bool operator()(const T& x, const T& y)     //重载operator(){return x > y;              //大于的比较逻辑}
};
namespace P
{                         template<class T, class Container=vector<int>,class Compare= less<int> >class priority_quque{public:priority_quque():_con(){}void AdjustUp(int child){Compare _com;int parent = (child - 1) / 2;while (parent >= 0){if(_com(_con[child],_con[parent])){std::swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}void AdjustDown(int parent){Compare _com;int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && _com(_con[child+1] , _con[child])){++child;}//如果父亲比孩子小,交换if(_com(_con[child],_con[parent])){std::swap(_con[parent], _con[child]);parent = child;                           //向下走child = parent * 2 + 1;}else{break;}}}void push(const T& x){_con.push_back(x);    //尾插一个数据AdjustUp(size() - 1);  //然后向上调整}void pop(){std::swap(_con[0], _con[size() - 1]);   //堆顶与最后一个元素交换,然后删除最后一个元素,然后从堆顶开始,向下调整_con.pop_back();AdjustDown(0);     //向下调整}T& top(){return _con.front();}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:Container _con;};}

三.deque的介绍

deque(双端队列):是一种双开口的 “连续” 空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

所说的来连续,并不是说都是连续的,在底层,deque是一段一段的数组,数组中存储的数据,然后有一个指针数组存储每一个数组的地址,这样,与vector比较,头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。
与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

在这里插入图片描述

但是有一个致命的缺陷是:中间插入和删除效率与下标随机访问的效率不高,这个缺陷是底层物理结构所导致的;

为什么选择deque作为stack和queue的底层默认容器?

stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;
queue是先进先出的特殊线性数据结构,只要具有push_back和pop_front操作的线性结构,都可以作为queue的底层容器,比如list。
但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

1.stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。
结合了deque的优点,而完美的避开了其缺陷。

请添加图片描述

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

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

相关文章

探索人工智能基础:从概念到应用【文末送书-42】

文章目录 人工智能概念人工智能基础【文末送书-42】 人工智能概念 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;作为当今科技领域的热门话题&#xff0c;已经深刻地影响着我们的生活和工作。但是&#xff0c;要理解人工智能&#xff0c;我们首先需…

2024年R1快开门式压力容器操作证考试题库及R1快开门式压力容器操作试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年R1快开门式压力容器操作证考试题库及R1快开门式压力容器操作试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人…

使用OpenCV实现人脸特征点检测与实时表情识别

引言&#xff1a; 本文介绍了如何利用OpenCV库实现人脸特征点检测&#xff0c;并进一步实现实时表情识别的案例。首先&#xff0c;通过OpenCV的Dlib库进行人脸特征点的定位&#xff0c;然后基于特征点的变化来识别不同的表情。这种方法不仅准确度高&#xff0c;而且实时性好&am…

C#中解决字符串在编译后无法修改的情况

文章目录 一、配置文件二、使用方式对于.NET Framework应用程序&#xff08;使用app.config&#xff09;对于.NET Core和.NET 5/6应用程序&#xff08;使用appsettings.json&#xff09; 三、应用实例 一、配置文件 在C#等编程语言中&#xff0c;硬编码&#xff08;直接在代码…

深度学习_20_卷积中的填充与步幅

如果图片本身比较小&#xff0c;卷积之后输出也会很小&#xff0c;那么可以在图片与卷积核相乘之前先填充一下&#xff0c;让输出为预期大小 一般填充后输入&#xff0c;输出相同 当图片比较大的时候&#xff0c;如果利用卷积核去得到我们想要的大小的话&#xff0c;得用到多层…

HDS-NAS分配资源并挂载win和linux

1、首先创建系统文件。 选择nas存储池 2、根据自己的需求创建相应的挂载方式 3、window配置 配置成功 最后即可在window系统网络位置映射网络即可&#xff0c; 格式为\\123.3.4.5\test 注&#xff1a;IP地址 4、liunx挂载方式 创建完成之后即可挂载&#xff0c;注意目的主…

数据结构面试常见问题之Insert or Merge

&#x1f600;前言 本文将讨论如何区分插入排序和归并排序两种排序算法。我们将通过判断序列的有序性来确定使用哪种算法进行排序。具体而言&#xff0c;我们将介绍判断插入排序和归并排序的方法&#xff0c;并讨论最小和最大的能区分两种算法的序列长度。 &#x1f3e0;个人主…

Python+Appium实现自动化测试的使用步骤

一、环境准备 1.脚本语言&#xff1a;Python3.x IDE&#xff1a;安装Pycharm 2.安装Java JDK 、Android SDK 3.adb环境&#xff0c;path添加E:\Software\Android_SDK\platform-tools 4.安装Appium for windows&#xff0c;官网地址Redirecting 点击下载按钮会到GitHub的下载…

Vulnhub靶机:Kioptrix_2014

一、介绍 运行环境&#xff1a;Virtualbox和vmware 攻击机&#xff1a;kali&#xff08;192.168.56.101&#xff09; 靶机&#xff1a;Kioptrix: 2014&#xff08;192.168.56.108&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://ww…

金融知识分享系列之:KD指标

金融知识分享系列之&#xff1a;KD指标 一、KD指标二、KD指标计算三、KD指标原理四、KD指标应用 一、KD指标 KD信号提供入场的工具 名称&#xff1a;随机震荡指标参数&#xff1a;&#xff08;9,3,3&#xff09;组成&#xff1a;K线&#xff0c;D线&#xff0c;20轴&#xff0…

GEE遥感云大数据林业应用典型案例及GPT模型应用

近年来遥感技术得到了突飞猛进的发展&#xff0c;航天、航空、临近空间等多遥感平台不断增加&#xff0c;数据的空间、时间、光谱分辨率不断提高&#xff0c;数据量猛增&#xff0c;遥感数据已经越来越具有大数据特征。遥感大数据的出现为相关研究提供了前所未有的机遇&#xf…

LeetCode困难题----84.柱状图中的最大矩形

今天刷LeetCode时遇到了一个很有意思的题: 看了半天题解还是没理解他的代码想要表达的是什么意思,在思考了很久之后,终于,我理解了这道题,接下来让我带你们走进这道题。 这道题的大概意思是,给你一个heights[]数组,(宽为1)让你求出他们可以组合出的最大面积 首先,我们先用暴力法…

一些刷题需要用的大数据

无符号版本和有符号版本的区别就是有符号类型需要使用一个bit来表示数字的正负。 如果需声明无符号类型的话就需要在类型前加上unsigned。 整型的每一种都分为&#xff1a;无符号&#xff08;unsigned&#xff09;和有符号&#xff08;signed&#xff09;两种类型&#xff08;f…

进阶二叉树

目录 二叉树 二叉搜索树 二叉搜索树的定义 二叉搜索树的操作 哈夫曼树 哈夫曼树的定义 哈夫曼树的构造 哈夫曼树的性质 平衡二叉树 平衡二叉树的定义&#xff1a; 平衡二叉树的插入调整 1.LL插入/LL旋转 2.RR插入/RR旋转 3.LR插入/LR旋转 4.RL插入/RL旋转 二叉树…

mac【启动elasticsearch报错:can not run elasticsearch as root

mac【启动elasticsearch报错&#xff1a;can not run elasticsearch as root 问题原因 es默认不能用root用户启动&#xff0c;生产环境建议为elasticsearch创建用户。 解决方案 为elaticsearch创建用户并赋予相应权限。 尝试了以下命令创建用户&#xff0c;adduser esh 和u…

分布式之Skywalking

Skywalking skywalking是一个apm系统&#xff0c;包含监控&#xff0c;追踪&#xff0c;并拥有故障诊断能力的 分布式系统 一、Skywalking介绍 1.什么是SkyWalking Skywalking是由国内开源爱好者吴晟开源并提交到Apache孵化器的产品&#xff0c;它同时吸收了Zipkin /Pinpoint …

【JS】替换文本为emjio表情

最终效果展示 T1 T2 T3 T4 需求 把评论你好帅啊啊啊[开心][开心]&#xff0c;[开心] 替换为图片 思路 正则match提取[开心]到一个数组数组去重创建img标签img标签转文本. 。例&#xff1a;&#xff08;el.outerHTML&#xff09;&#xff0c;将el元素转文本字符串replaceAll…

流畅的 Python 第二版(GPT 重译)(十三)

第二十四章&#xff1a;类元编程 每个人都知道调试比一开始编写程序要困难两倍。所以如果你在编写时尽可能聪明&#xff0c;那么你将如何调试呢&#xff1f; Brian W. Kernighan 和 P. J. Plauger&#xff0c;《编程风格的要素》 类元编程是在运行时创建或自定义类的艺术。在 P…

新版 mac 浏览器乱码

现象 如下图&#xff0c;chrome 浏览器有的乱码了 解决方法 删除字体集中的微软雅黑&#xff08;下图已删除&#xff09;&#xff0c;右键移除

算法打卡day18|二叉树篇07|Leetcode 530.二叉搜索树的最小绝对差、501.二叉搜索树中的众数、236. 二叉树的最近公共祖先

算法题 Leetcode 530.二叉搜索树的最小绝对差 题目链接:530.二叉搜索树的最小绝对差 大佬视频讲解&#xff1a;二叉搜索树的最小绝对差视频讲解 个人思路 因为是在二叉搜索树求绝对差&#xff0c;而二叉搜索树是有序的&#xff0c;那就把它想成在一个有序数组上求最值&…