C++:Stack和Queue的模拟实现

                                                    创作不易,感谢三连! 

一、容器适配器

       适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

      就如同是电源适配器将不适用的交流电变得适用一样,模板 B 将不适合直接拿来用的模板 A 变得适用了,因此我们可以将模板 B 称为 B 适配器。 容器适配器也是同样的道理,简单的理解容器适配器,其就是将不适用的序列式容器(包括 vector、deque 和 list)变得适用。 容器适配器的底层实现和模板 A、B 的关系是完全相同的,即通过封装某个序列式容器,并重新组合该容器中包含的成员函数,使其满足某些特定场景的需要。

二、deque的简单了解

      我们知道,vector支持下标的随机访问,但是头部和中部插入删除效率低下,且需要频繁扩容,而list虽然任意位置插入删除高效,但是不支持随机访问,所以就有人在思考,能否找到一种数据结构可以替代他俩呢??于是就有了双端队列这个数据结构,但实际上双端队列并无法替代vector和list,并且后来成为了最适合stack和queue的底层容器,这就是典型的相当皇上没当成,却成了丫鬟。

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

       deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:
 

     双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,重任落在了deque的迭代器身上。

下面我们进行总结:

我们可以看到:

1、与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。

2、与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

3、但是,deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list。

4、deque的应用并不多,但我们发现他的头插头删和尾插尾删的效率特别高,所以目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构。

5、还有第二个缺陷就是:

(1)如果我们假定buff每个数组大小一样大,那么随机访问的效率就会高,因为我们减掉该层的当前元素,然后/10可以跳层,再%10就可以跳到该层对应的位置,但是需要中间的插入和删除的话,那么为了维持每层的数组大小,就可能需要挪动一堆数据。

(2)如果我们假定每个buff数组的大小不一样大,那么如果中间的插入删除就不需要挪数据了,效率会提高,但是随机访问的效率就会变低了,因为不知道每层有多少元素,所以无法直接跳层,而是要一个个去遍历才能访问到某个元素。

     因此各有利弊不可兼得,在SGI版本下选择的是buff数组固定大小,所以他的迭代器设置得非常复杂。

那deque是如何借助其迭代器维护其假想连续的结构呢? 

三、Stack介绍

Stack文档介绍

1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其只能从容器的一端进行元素的插入与提取操作。

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

3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:
empty:判空操作
back:获取尾部元素操作
push_back:尾部插入元素操作
pop_back:尾部删除元素操作

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

四、Queue介绍

Queue文档介绍

1. 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。

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

3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:
empty:检测队列是否为空
size:返回队列中有效元素的个数
front:返回队头元素的引用
back:返回队尾元素的引用
push_back:在队列尾部入队列
pop_front:在队列头部出队列

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

五、为什么选择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的优点,而完美的避开了其缺陷。

六、适配器模式下的stack模拟实现

using namespace std;
namespace cyx
{template<class T,class Container=deque<T>>// 可以用vectoe list deque作为适配器class stack{public:bool empty() const{return _con.empty();}size_t size() const{return _con.size();}const T& top() const{return _con.back();}T& top(){return _con.back();}void push(const T&val) {_con.push_back(val);}void pop(){_con.pop_back();}void swap(stack<T> &s){_con.swap(s._con);}private:Container _con;//适配器};

七、适配器模式下的queue模拟实现

namespace cyx
{template<class T,class Container=deque<T>>//该适配器可以用list deque  如果是用vector不太合适,因为不支持头删class queue{public:bool empty() const{return _con.empty();}size_t size(){return _con.size();}T& front(){return _con.front();}const T& front() const {return _con.front();}T& back(){return _con.back();}const T& back() const{return _con.back();}void push(const T&val){_con.push_back(val);}void pop(){_con.pop_front();}void swap(queue<T> &q){_con.swap(q._con);}private:Container _con;};

八、遍历的一般形式 

stack

queue

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

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

相关文章

css实现背景渐变叠加

线性渐变效果图: .box{width: 100vw;height: 100vh;background:linear-gradient(to bottom,transparent,#fff 30%),linear-gradient(to right,pink,skyblue);}径像渐变效果图&#xff1a; .box{width: 100vw;height: 100vh;background:linear-gradient(to bottom,transparent,#…

【JavaEE初阶】 JVM类加载简介

文章目录 &#x1f343;前言&#x1f332;类加载过程&#x1f6a9;加载&#x1f6a9;验证&#x1f6a9;准备&#x1f6a9;解析&#x1f6a9;初始化 &#x1f384;双亲委派模型&#x1f6a9;什么是双亲委派模型&#xff1f;&#x1f6a9;双亲委派模型的优点 ⭕总结 &#x1f343…

Vue.js 实用技巧:深入理解 Vue.mixin

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

开发一套小程序所需的费用取决于多个因素

随着移动互联网的发展&#xff0c;小程序已经成为许多企业和个人推广业务和服务的重要工具。 不过&#xff0c;对于很多想要开发小程序的人来说&#xff0c;最大的疑问就是开发一套小程序要花多少钱。 这个问题的答案并不是固定的&#xff0c;因为开发一个小程序的成本取决于几…

业务代码中如何使用装饰器模式?

装饰器模式&#xff08;Decorator Pattern&#xff09;介绍 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;我们可以动态地给一个对象添加额外的职责。而不是通过继承增加子类的方式来扩展对象的功能&#xff0c;装饰器模式使用组合的…

Java注解介绍

Java注解 注解介绍元注解RetentionTargetDocumentedInherited接口类测试结果 注解介绍 Java注解&#xff08;Annotation&#xff09;是一种元数据&#xff08;Metadata&#xff09;的形式&#xff0c;它可以被添加到Java代码中的类、方法、变量、参数等元素上&#xff0c;以提…

AI时代PPT如何制作?用这10款pptai生成器一键制作!

ppt如何制作&#xff1f; 这可能是很多职场人或大学生日常头疼的问题&#xff0c;职场上随便一个工作汇报、提案展示、团队会议&#xff0c;学校里的小组作业、论文答辩等场景&#xff0c;都会用到ppt。 都说人是视觉动物&#xff0c;在两份文档内容质量一致的情况下&#xf…

Linux的top命令解析

Top命令是什么 TOP命令是Linux下常用的性能分析工具&#xff0c;能够实时显示系统中各个进程的资源占用状况。 TOP是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终止该程序为止.比较准确的说,top命令提供了实时的对系…

Day16:信息打点-语言框架开发组件FastJsonShiroLog4jSpringBoot等

目录 前置知识 指纹识别-本地工具-GotoScan&#xff08;CMSEEK&#xff09; Python-开发框架-Django&Flask PHP-开发框架-ThinkPHP&Laravel&Yii Java-框架组件-Fastjson&Shiro&Solr&Spring 思维导图 章节知识点 Web&#xff1a;语言/CMS/中间件/…

【物联网】stm32芯片结构组成,固件库、启动过程、时钟系统、GPIO、NVIC、DMA、UART以及看门狗电路的全面详解

一、stm32的介绍 1、概述 stm32: ST&#xff1a;指意法半导体 M&#xff1a;指定微处理器 32&#xff1a;表示计算机处理器位数 与ARM关系:采用ARM推出cortex-A&#xff0c;R,M三系中的M系列&#xff0c;其架构主要基于ARMv7-M实现 ARM分成三个系列&#xff1a; Cortex-A&…

开源模型应用落地-工具使用篇-Ollama(六)

一、前言 在AI大模型百花齐放的时代&#xff0c;很多人都对新兴技术充满了热情&#xff0c;都想尝试一下。但是&#xff0c;实际上要入门AI技术的门槛非常高。除了需要高端设备&#xff0c;还需要面临复杂的部署和安装过程&#xff0c;这让很多人望而却步。不过&#xff0c;随着…

RFID-科技的“隐秘耳语者”

RFID-科技的“隐秘耳语者” 想象一下&#xff0c;你身处一个光线昏暗的环境中&#xff0c;周围的一切都被厚厚的阴影笼罩。这时&#xff0c;你需要识别并获取一个物体的信息&#xff0c;你会选择怎么做&#xff1f;是点亮灯光&#xff0c;用肉眼仔细观察&#xff0c;还是打开扫…

神经网络的矢量化,训练与激活函数

我们现在再回到我们的神经元部分&#xff0c;来看我们如何用python进行正向传递。 单层的正向传递&#xff1a; 我们回到我们的线性回归的函数。我们每个神经元通过上述的方法&#xff0c;就可以得到我们的激发值&#xff0c;从而可以继续进行下一层。 我们用这个方法就可以得…

智慧城市如何助力疫情防控:科技赋能城市安全

目录 一、引言 二、智慧城市与疫情防控的紧密结合 三、智慧城市在疫情防控中的具体应用 1、智能监测与预警系统 2、智慧医疗与健康管理 3、智能交通与物流管理 4、智慧社区与基层防控 四、科技赋能城市安全的未来展望 五、结论 一、引言 近年来&#xff0c;全球范围内…

Platformview在iOS与Android上的实现方式对比

Android中早期版本Platformview的实现基于Virtual Display。VirtualDisplay方案的原理是&#xff0c;先将Native View绘制到虚显&#xff0c;然后Flutter通过从虚显输出中获取纹理并将其与自己内部的widget树进行合成&#xff0c;最后作为Flutter在 Android 上更大的纹理输出的…

链表|206.反转链表

力扣题目链接 struct ListNode* reverseList(struct ListNode* head){//保存cur的下一个结点struct ListNode* temp;//pre指针指向前一个当前结点的前一个结点struct ListNode* pre NULL;//用head代替cur&#xff0c;也可以再定义一个cur结点指向head。while(head) {//保存下…

测试常用的Linux命令

前言 直接操作硬件 将把操作硬件的代码封装成系统调用&#xff0c;供程序员使用 虚拟机软件 可以模拟的具有完整硬件系统的功能 可以在虚拟机上安装不同的操作系统 Linux内核只有一个&#xff0c;发行版有很多种 内核来运行程序和管理像磁盘和打印机等硬件设备的核心程序 终端…

高清数学公式视频素材、科学公式和方程式视频素材下载

适用于科普、解说的自媒体视频剪辑素材&#xff0c;黑色背景数学、科学公式和方程式视频素材下载。 视频编码&#xff1a;H.264 | 分辨率&#xff1a;3840x2160 (4K) | 无需插件 | 文件大小&#xff1a;16.12MB 来自PR视频素材&#xff0c;下载地址&#xff1a;https://prmuban…

NTFS Disk by Omi NTFS for mac v1.1.4中文版

NTFS Disk by Omi NTFS for Mac&#xff1a;NTFS文件系统的无缝桥梁 软件下载&#xff1a;NTFS Disk by Omi NTFS for mac v1.1.4中文版 &#x1f310; 跨平台访问&#xff0c;文件无阻 NTFS Disk by Omi NTFS for Mac 为您的Mac提供了对NTFS文件系统的无缝访问。无论您是在Win…

Crow 编译和环境搭建

Crow与其说是编译&#xff0c;倒不如说是环境搭建。Crow只需要包含头文件&#xff0c;所以不用编译生成lib。 Crow环境搭建 boost&#xff08;可以不编译boost&#xff0c;只需要boost头文件即可&#xff09;asio &#xff08;可以不编译&#xff0c;直接包含头文件。不能直接…