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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

阿里云服务器怎么使用?3分钟搭建网站教程2024新版

使用阿里云服务器快速搭建网站教程&#xff0c;先为云服务器安装宝塔面板&#xff0c;然后在宝塔面板上新建站点&#xff0c;阿里云服务器网aliyunfuwuqi.com以搭建WordPress网站博客为例&#xff0c;来详细说下从阿里云服务器CPU内存配置选择、Web环境、域名解析到网站上线全流…

代码随想录第53天|● 1143.最长公共子序列 ● 1035.不相交的线 ● 53. 最大子序和 动态规划

文章目录 ● 1143.最长公共子序列思路&#xff1a;代码一&#xff1a;dp二维数组代码二&#xff1a;滚动数组 ● 1035.不相交的线思路&#xff1a;代码&#xff1a;&#xff08;滚动数组&#xff09; ● 53. 最大子序和 动态规划思路代码&#xff1a;代码二&#xff1a;单一元素…

许多人可能还不了解这个信息差:美赛的第一批 EI 已经录用,不用再犹豫啦

格局打开&#xff0c;美赛论文转学术论文发表 &#x1f680;&#x1f680; 各位同学&#xff0c;美赛已经结束了一段时间&#xff0c;你们是否还在焦急地等待最终成绩的公布&#xff1f;一些有远见的同学已经提前收到了一份喜讯&#xff1a;他们的美赛论文已被转化为学术论文并…

2024年博管办香江学者、澳门青年学者、中德博士后 交流项目申报工作启动

近日&#xff0c;中国博士后科学基金会官网发布了2024年博士后国&#xff08;境&#xff09;外学术交流项目申报指南&#xff0c;以下知识人网小编仅转载香江学者计划、澳门青年学者计划、中德博士后交流项申报指南并做重点解读。 知识人网整理 各省、自治区、直辖市及新疆生产…

Sora的双重边缘:视频生成的革新与就业的再思考

随着科技的日新月异&#xff0c;人工智能&#xff08;AI&#xff09;和机器学习&#xff08;ML&#xff09;技术如潮水般涌入我们的日常生活&#xff0c;为各个领域带来了翻天覆地的变化。在这一浪潮中&#xff0c;Sora作为一款前沿的AI视频生成工具&#xff0c;凭借其高度逼真…

vue 使用 PrintJs 实现打印pdf效果

一、print.js介绍 Print.js主要是为了帮助我们直接在应用程序中打印PDF文件&#xff0c;而无需离开界面&#xff0c;并且不使用嵌入。对于用户不需要打开或下载PDF文件的特殊情况&#xff0c;他们只需要打印它们。 例如&#xff0c;当用户请求打印在服务器端生成的报告时&…

便携式测速仪的工作原理

TH-LS5】便携式测速仪的工作原理主要基于多普勒效应。当测速仪发射电磁波并碰触到物体时&#xff0c;电磁波会被反射回来。如果触碰到的物体有朝向或背向的位移运动&#xff0c;那么测速仪发射与反射回来的电磁波之间会存在一个频率差。这个频率差会被测速仪捕获&#xff0c;并…

上海雷卯可以解决YPbPr/ YCbCr接口 ESD/EOS静电浪涌问题

YPbPr /YCbCr 接口传输的是视频信号&#xff0c;不传输音频信号。YPbPr 和 YCbCr 都是视频信号的颜色编码格式&#xff0c;多应用于机顶盒&#xff08;Set-top box&#xff09;,TV电视&#xff0c;投影仪&#xff0c;游戏机和DVD播放器。 YPbPr&#xff1a;是一种模拟视频接口…

2.DOM-事件基础(注册事件、tab栏切换)(案例:注册、轮播图)

案例 注册事件 <!-- //disabled默认情况用户不能点击 --><input type"button" value"我已阅读用户协议(5)" disabled><script>// 分析&#xff1a;// 1.修改标签中的文字内容// 2.定时器// 3.修改标签的disabled属性// 4.清除定时器// …

前端实现扫同一个二维码,可以跳转到微信小程序和支付宝小程序?

前端如何实现扫同一个二维码&#xff0c;可以跳转到微信小程序和支付宝小程序&#xff1f; 不知道大家有没有遇到过这样的需求&#xff1a;扫描同一个二维码&#xff0c;要如何区分是微信还是支付宝扫码。然后进入微信和支付宝的小程序&#xff1f;&#xff1f; 就我目前所知道…

部署 LVS(nginx)+keepalived高可用负载均衡集群

目录 一、集群的概述 1、什么是集群 2、普通集群与负载均衡集群 2.1 普通集群&#xff08;Regular Cluster&#xff09; 2.2 负载均衡集群&#xff08;Load Balancing Cluster&#xff09; 2.3 高可用集群&#xff08;High Availability Cluster&#xff09; 2.4 区别 …

网站开发之旅:从概念到实现

在我成为一名专业的网站开发者的过程中&#xff0c;我有幸参与了多个激动人心的项目。其中&#xff0c;一个我印象尤为深刻的经历是&#xff0c;开发一个名为“文案推荐网”的主题网站&#xff08;www.zimeiti.love&#xff09;。这个项目不仅让我深入了解了网站开发的各个方面…

JVM优化

1. JVM内存 JVM内存&#xff1a; 1&#xff0c;虚拟机栈&#xff1a;每个线程有一个私有的栈&#xff0c;随着线程的创建而创建。每个方法会创建一个栈帧&#xff0c;栈帧中存放了局部变量表&#xff08;基本数据类型和对象引用&#xff09;、操作数栈、方法出口等 栈的大小可…

构建cef基本框架及构建过程中的参数说明

文章目录 准备源码版本编译版本结构编译过程写了好多CEF的内容了,发现一个最初的CEF helloworld的过程都没有写,也就是如何搭建这个CEF框架。今天把这个过程记录一下。 准备源码版本 在度娘上搜cef源码,一般得到的是https://bitbucket.org/chromiumembedded/cef/这个网址,…

linux下改变主机名,永久生效的方法

hostnamectl set-hostname test 例子 #支持大写必须就要这样写 hostnamectl set-hostname 名称 --static

Docker安装主从数据库

我自己的主数据库名字 user_muster 密码是123456 从数据库 就是slave2 名字是root 密码是123456 首先开启docker后直接执行命令 docker run -d \ -p 3307:3306 \ -v /xk857/mysql/master/conf:/etc/mysql/conf.d \ -v /xk857/mysql/master/data:/var/lib/mysql \ -e MYSQL_…

长非编码RNA(lncRNA)LINC00339编码的肽段促进滋养层细胞与子宫内膜细胞粘附的研究 AbMole

胚胎植入是一个复杂的过程&#xff0c;受多种因素影响&#xff0c;尤其是子宫内膜&#xff08;endometrium&#xff09;与胚泡&#xff08;blastocyst&#xff09;之间的相互作用。子宫内膜接受性&#xff08;Endometrial Receptivity, ER&#xff09;是指子宫内膜在适当的功能…

springboot+xjar加密打包部署教程

需求背景 为了跟上时代的步伐&#xff0c;为了更好的生存。开个玩笑&#xff0c;就是心血来潮&#xff0c;使用xjar加密部署jar包&#xff0c;于是就测试一下。 xjar教程 1-maven配置文件修改 首先找到自己ideal配置的maven文件夹&#xff0c;然后找到apache-maven-3.9.3\co…

基于Pytorch搭建分布式训练环境

Pytorch系列 文章目录 Pytorch系列前言一、DDP是什么二、DPP原理terms、nodes 和 ranks等相关术语解读DDP 的局限性为什么要选择 DDP 而不是 DP代码演示1. 在一个单 GPU 的 Node 上进行训练&#xff08;baseline&#xff09;2. 在一个多 GPU 的 Node 上进行训练临门一脚&#x…

js【详解】event loop(事件循环/事件轮询)

event loop 是异步回调的实现原理 js 代码的执行过程 从前到后&#xff0c;一行一行执行如果某一行执行报错&#xff0c;则停止下面代码的执行先把同步代码执行完&#xff0c;再执行异步 event loop 图解 以下方代码为例&#xff1a; 第1步 将第 1 行代码放入调用栈 将要执行第…