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.mzph.cn/news/753440.shtml

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

相关文章

【玩转AI绘画】有奖活动火热进行中,参与赢取耳机键盘等好礼!

AI 绘画发展迅猛&#xff0c;各种创新插件如 animatediff、instantid、controlnet 、roop 等遍地开花&#xff0c;极大地激发了 StableDiffusion 的应用潜力。AI 绘画的使用场景不断扩展&#xff0c;如 AI 视频制作、Q 版头像生成、老照片修复、照片高清化等。腾讯云高性能应用…

【OceanBase诊断调优】—— 敏捷诊断工具obdiag一键分析OB集群日志设计与实践

最近总结一些诊断OCeanBase的一些经验&#xff0c;出一个【OceanBase诊断调优】专题&#xff0c;也欢迎大家贡献自己的诊断OceanBase的方法。 1. 前言 obdiag定位为OceanBase敏捷诊断工具。1.2版本的obdiag支持诊断信息的一键收集&#xff0c;光有收集信息的能力&#xff0c;…

【nnUNetv2实践】一、nnUNetv2安装

nnUNet是一个自适应的深度学习框架&#xff0c;专为医学图像分割任务设计。以下是关于nnUNet的详细解释和特点&#xff1a; 自适应框架&#xff1a;nnUNet能够根据具体的医学图像分割任务自动调整模型结构、训练参数等&#xff0c;从而避免了繁琐的手工调参过程。自动化流程&am…

提升地理空间分析效率,火山引擎ByteHouse上线GIS能力

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 在数字化时代&#xff0c;地理空间分析&#xff08;Geospatial Analytics&#xff09;成为辅助企业市场策略洞察的重要手段。无论是广告投放的精准定位&#xff0c;…

Leetcode 1. 两数之和

心路历程&#xff1a; 很简单的题&#xff0c;双层暴力就可以&#xff0c;用双指针的话快一点。暴力时间复杂度O( n 2 n^2 n2)&#xff0c;双指针时间复杂度O(nlogn) O(n) O(n) O(nlogn)。 注意的点&#xff1a; 1、题目需要返回原数组的索引&#xff0c;所以排序后还需要…

豆瓣电影信息爬取与可视化分析

目录 一、项目背景 二、代码 三、总结 一、项目背景 &#xff08;1&#xff09;利用requests库采集豆瓣网分类排行榜 (“https://movie.douban.com/chart”)中各分类类别前100部电影的相关信息并存储为csv文件。 &#xff08;2&#xff09;利用获取的13个分类类别共1300部电…

Linux:搭建ntp服务器

我准备两个centos7服务器 一个为主服务器连接着外网&#xff0c;并且搭建了ntp服务给其他主机同步 另外一个没有连接外网&#xff0c;通过第一台设备去同步时间 首先两个服务器都要安装ntp软件 yum -y install ntp 再把他俩的时间都改成别的 左侧的是主服务器&#xff0c;主…

idea项目mapper.xml中的SQL语句黄色下划线去除

问题描述 当我们使用idea开发java项目时&#xff0c;经常会与数据库打交道&#xff0c;一般在使用mybatis的时候需要写一大堆的mapper.xml以及SQL语句&#xff0c;每当写完SQL语句的时候总是有黄色下划线&#xff0c;看着很不舒服。 解决方案&#xff1a; 修改idea的配置 Edi…

服务器段的连接端口和监听端口编程实现

new ServerSocket(int)是开启监听端口&#xff0c;并不是连接端口。真正的连接端口是随机开辟的空闲端口&#xff0c;当连接创建完成后&#xff0c;监听关口可以继续等待下一次连接请求&#xff0c;处于空闲等待状态。 编程实现方式 1 、主线程一直处于阻塞等待状态&#xff0c…

C 练习实例77-指向指针的指针-二维数组

关于数组的一些操作 #include<stdio.h> #include<stdio.h> void fun(int b[],int length) {for(int i0;i<length;i){printf("%d ",b[i]);}printf("\n");for(int i0;i<length;i){ //数组作为形参传递&#xff0c;传递的是指针&#xff0…

人工智能如何撬动新质生产力发展?

全国两会期间&#xff0c;“新质生产力”成为高频词&#xff0c;引发高度关注。新质生产力是由技术革命性突破、生产要素创新性配置、产业深度转型升级催生的当代先进生产力。而人工智能被视为形成新质生产力的重要引擎。 随着人工智能&#xff08;AI&#xff09;技术跨越奇点…

Python3+RIDE+RobotFramework自动化测试框架搭建

Python2.7已于2020年1月1日开始停用&#xff0c;之前RF做自动化都是基于Python2的版本。 没办法&#xff0c;跟随时代的脚步&#xff0c;我们也不得不升级以应用新的控件与功能。 升级麻烦&#xff0c;直接全新安装。 一、Python安装 最新版Python下载地址&#xff1a;http…

Python环境下基于注意力机制的小样本轴承故障诊断

传统的基于特征提取与分类相结合的轴承智能诊断算法&#xff0c;对信号处理要求很高的专家经验&#xff0c;既费时又缺乏通用性。基于深度学习的智能轴承故障诊断方由于具有强大的特征提取能力&#xff0c;避免了繁琐复杂的特征提取工作&#xff0c;但是大多数研究都是在标准数…

共谋企业出海新篇章纷享销客荣获数字中国企业峰会“卓越成果奖”

3月9日&#xff0c;2024数字中国企业峰会在杭州西湖中维香溢大酒店成功举办&#xff0c;众多数字化领域专家、知名企业 CIO 代表到场。峰会旨在推动数字化转型与创新发展&#xff0c;为企业出海和国际合作搭建交流与合作的平台。本次峰会的颁奖环节&#xff0c;纷享销客凭借其卓…

【已解决】MySQL:常用的除法运算+精度处理+除数为0处理

目录 问题现象&#xff1a; 问题分析&#xff1a; 拓展&#xff1a; 1、除法运算&#xff1a; 拓展&#xff1a;MySQL中常用的几种除法运算 1、取整除法 2、浮点数除法 3、取余除法 4、向上取整除法 5、向下取整除法 2、运算结果的精度处理 1.1、浮点数 1.2、总位数 1.3、…

android 怎么自定义view

首先了解view的绘制流程: 所以onmeasure ---测量view onlayout---确定view大小----》所以继承ViewGroup必须要重写onlayout,确定子view 而onDraw----是继承view时候需要操作的。 所以:自定义ViewGroup一般是利用现有的组件根据特定的布局方式来组成新的组件。 自定义Vi…

python打包时遇见第三方包有隐藏依赖或者出现依赖错误

使用pyinstaller 打包成exe 文件步骤&#xff1a; 1.创建虚拟环境&#xff0c;并激活虚拟环境 #创建虚拟环境 python -m venv myenv #激活虚拟环境&#xff08;windows&#xff09; myenv\Scripts\activate2.导出需要的依赖 pip freeze > requirements.txt 或者 pip list …

AutoCAD 2020:三维建模与渲染,设计未来的建筑蓝图

AutoCAD 2020是一款功能强大且广泛应用的计算机辅助设计软件&#xff0c;它以其卓越的性能和丰富的功能&#xff0c;满足了机械、建筑、家居、纺织等诸多行业的设计需求。以下是AutoCAD 2020的一些主要功能介绍&#xff1a; 保存和安装优化&#xff1a;AutoCAD 2020在性能上进…

观成科技-基于自适应学习的人工智能加密流量检测技术

1.前言 人工智能技术的广泛应用正在深刻改变我们的生活。在网络安全领域&#xff0c;基于机器学习的检测技术也应用在许多场景中。随着信息技术的迅猛发展和数字化转型的深入推进&#xff0c;加密技术逐渐成为保障网络安全和数据隐私的核心手段&#xff0c;而基于机器学习的检…

每日五道java面试题之mybatis篇(四)

目录&#xff1a; 第一题. 映射器#{}和${}的区别第二题. 模糊查询like语句该怎么写?第三题. 在mapper中如何传递多个参数?第四题. Mybatis如何执行批量操作第五题 MyBatis框架适用场景 第一题. 映射器#{}和${}的区别 #{}是占位符&#xff0c;预编译处理&#xff1b;${}是拼接…