C++ STL stack queue

news2024/11/27 12:29:22

目录

一.stack 介绍

 二.stack 使用

三.stack 模拟实现

普通版本:

适配器版本:

四.queue的介绍

五. queue使用

六.queue模拟实现

七.deque介绍

1.容器适配器

2.deque的简单介绍

3.deque的缺陷

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


一.stack 介绍

stack------reference

1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。
2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。
3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:

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

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

 二.stack 使用

函数说明接口说明
stack()构造空的栈
empty()检测stack是否为空
size()返回stack中元素的个数
top()返回栈顶元素的引用
push()将元素val压入stack中
pop()将stack中尾部的元素弹出

三.stack 模拟实现

普通版本:

stack的模拟实现非常简单,我们利用已经学过的vector去封装他的几个接口就可以了。

	template<class T>
	class Stack
	{
	public:
		Stack()
		{}

		const T& top()
		{
			return _v.back();
		}

		void pop()
		{
			return _v.pop_back();
		}

		void push(const T& val)
		{
			_v.push_back(val);
		}

		size_t size()
		{
			return _v.size();
		}

		bool empty()
		{
			return _v.empty();
		}
	private:
		vector<T> _v;
	};
    
    int main()
    {
	    Stack<int> st;
	    st.push(100);
	    st.push(200);
	    st.push(300);
	    st.push(400);

	    while (!st.empty())
	    {
		    cout << st.top()<<" ";
		    st.pop();
	    }
        return 0;
    }

 这里我们使用的是vector做的底层容器,在std::stack中,底层容器是deque并且支持切换成其他容器,这也就是stack被叫做容器适配器的原因。

适配器版本:

容器适配器,我们仅仅需要利用一个类模板参数就可以了,一个类模板参数就可以控制底层存储数据的容器类型,是vector还是list又或者是deque。

    //容器适配器class Container = vector<T>,class Container = list<T>....
    template<class T ,class Container >
	class Stack
	{
	public:
		Stack()
		{}

		const T& top()
		{
			return _v.back();
		}

		void pop()
		{
			return _v.pop_back();
		}

		void push(const T& val)
		{
			_v.push_back(val);
		}

		size_t size()
		{
			return _v.size();
		}

		bool empty()
		{
			return _v.empty();
		}
	private:
		Container _v;
	};

    int main()
    {
	    Stack<int,list<int>> st;
	    st.push(100);
	    st.push(200);
	    st.push(300);
	    st.push(400);

	    while (!st.empty())
	    {
		    cout << st.top()<<" ";
		    st.pop();
	    }
        return 0;
    }

在类模板的哪里也是可以给缺省参数,就可以实现默认存储容器。

template<class T ,class Container = deque<T>>

四.queue的介绍

queue-----reference

1. 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。
2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。
3. 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:

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

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

五. queue使用

函数声明接口说明
queue()构造空的队列
empty()检测队列是否为空,是返回true,否则返回false
size()返回队列中有效元素的个数
front()返回队头元素的引用
back()返回队尾元素的引用
push()在队尾将元素val入队列
pop()将队头元素出队列

六.queue模拟实现

因为queue的接口中存在头删和尾插,因此使用vector来封装效率太低,故可以借助list来模拟实现queue,具体如下:

普通list版本:

    template<class T>
	class Queue
	{
	public:
		Queue()
		{
		}

		void push(const T& val)
		{
			_q.push_back(val);
		}

		void pop()
		{
			_q.pop_front();
		}

		const T& front()
		{
			return _q.front();
		}

		const T& back()
		{
			return _q.back();
		}

		size_t size()
		{
			return _q.size();
		}

		bool empty()
		{
			return _q.empty();
		}

	private:
		list<T> _q;
	};

适配器版本:

    template<class T,class Container=list<T>>
	class Queue
	{
	public:
		Queue()
		{
		}

		void push(const T& val)
		{
			_q.push_back(val);
		}

		void pop()
		{
			_q.pop_front();
		}

		const T& front()
		{
			return _q.front();
		}

		const T& back()
		{
			return _q.back();
		}

		size_t size()
		{
			return _q.size();
		}

		bool empty()
		{
			return _q.empty();
		}

	private:
		Container _q;
	};

 七.deque介绍

1.容器适配器

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

STL标准库中stack和queue的底层结构 :

虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stack和队列只是对其他容器的接口进行了包装,STL中stack和queue默认使用deque,比如:

2.deque的简单介绍

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

 同时从库中提供的接口来看,deque还提供了下标的随机访问的功能,但是deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组,其底层结构如下图所示:

 双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:

  3.deque的缺陷

与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是比vector高的。与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。
但是,deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构。

4.为什么选择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.coloradmin.cn/o/875616.html

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

相关文章

SpringBoot复习:(46)全局的bean懒加载是怎么实现的?

在application.properties中配置&#xff1a; spring.main.lazy-initializationtrue在运行SpringApplication的run方法时&#xff0c;代码如下&#xff1a; 其中调用了prepareContext,prepareContext代码如下&#xff1a; 当在配置文件中配置了spring.main.lazy-initializat…

中国1990-2021连续30年土地利用数据CLCD介绍及下载

CLCD数据介绍 CLCD(China Land Cover Dataset)数据集由武汉大学黄昕老师公布,黄昕老师基于Google Earth Engine上335,709景Landsat数据,制作中国年度土地覆盖数据集(annual China Land Cover Dataset, CLCD),包含1985+1990—2020中国逐年土地覆盖信息。 为此,黄昕老师…

学好Elasticsearch系列-索引的批量操作

本文已收录至 Github&#xff0c;推荐阅读 &#x1f449; Java 随想录 先看后赞&#xff0c;养成习惯。 点赞收藏&#xff0c;人生辉煌。 文章目录 基于 mget 的批量查询基于 bulk 的批量增删改增加删除修改 filter_path Elasticsearch 提供了 _bulk API 来执行批量操作&#x…

Web APIs 第六天

正则表达式介绍语法元字符修饰符 一.正则表达式介绍 ① 简介 用来匹配字符串中字符组合的模式在JavaScript中&#xff0c;正则表达式也是对象通常用来查找&#xff0c;替换那些符合正则表达式的文本&#xff0c;许多语言都支持正则表达式 ② 使用场景 验证表单&#xff1a…

解决Adobe Flash Player已被屏蔽

问题&#xff1a;该插件不支持 原因&#xff1a;现在浏览器默认禁用flash 博主当前使用的是谷歌浏览器Chrome 2个主要方法都已经失效 搜索一圈后&#xff0c;之前博客给出的2个主要方法都已经失效。 1、flash.cn 下载本地播放器 2、在chrome中打开flash的禁用开关 2023年解…

vm ubuntu20共享文件夹

问题: 根据教程开启共享文件夹后 ,在ubuntu 的/mnt里面没有hgfs目录,也没有共享的两个文件夹,执行如上命令可重新挂载共享目录 vmware-hgfsclient sudo vmhgfs-fuse .host:/ /mnt/ -o nonempty -o allow_other 之后通过find / -name 你的共享目录名字 查看是否加载成功 附…

总线基本概念

总线基本概念 为什么要用总线 总线是连接各个部件的信息传输线&#xff0c;是各个部件共享的传输介质。&#xff08;如果没有总线&#xff0c;那么每新增一个组件&#xff0c;就需要增加若干线和其余组件相连&#xff09; 在任何一个时刻&#xff0c;只能有一对设备&#xf…

第三章 图论 No.12欧拉回路与欧拉路径

文章目录 定义欧拉路径的性质&#xff1a;1123. 铲雪车边编号输出欧拉路径&#xff1a;1184. 欧拉回路点编号字典序最小输出欧拉路径&#xff1a;1124. 骑马修栅栏并查集判断有向图是否存在欧拉路径&#xff1a;1185. 单词游戏 定义 小学一笔画问题&#xff0c;每条边只经过一次…

pconsc4 安装

Pconsc4 安装遇到的问题 Pconsc4-github 按照红框给的一行命令&#xff0c;一行毁所有。 1 gcc and g not found # 1 Start by updating the packages list:sudo apt update# 2 Install the build-essential package by typing:sudo apt install build-essential## The comm…

83. 删除排序链表中的重复元素

题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 解题思路&#xff1a;从前往后遍历节点&#xff0c;如果当前节点和下一个节点的值相等&#xff0c;就跳过下一个节点 具体算法如下&#xff1a; current head如果 current!null…

如何使用CSS实现一个下拉菜单?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 使用CSS实现下拉菜单⭐ HTML 结构⭐ CSS 样式⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些…

SAP MIGO采购订单收货默认库存类型控制

在启用了QM模块的企业应用中&#xff0c;收货时针对库存类型就会有不同情况&#xff0c;参与质检的收到质检库存&#xff0c;不参与质检的收到非限制库存。 那么我一直没的遇到过关于应收到质检&#xff0c;而收到非限制库存的反馈。说明这样的问题不会发生&#xff0c;带着疑…

PyQt5设置按钮菜单和信号与槽函数的连接

目录 一、Qt Designer 在窗口中添加菜单和工具栏 二、源代码 1、界面代码 2、逻辑代码 3、演示 三、相关功能 一、Qt Designer 在窗口中添加菜单和工具栏 右键可以选择创建菜单栏。创建后双击【在这里输入】&#xff0c;然后输入菜单名&#xff0c;敲下回车确认&#xf…

OpenCV图像处理——图像平滑

目录 图像噪声椒盐噪声高斯噪声图像平滑简介均值滤波高斯滤波中值滤波 图像噪声 椒盐噪声 随机出现的黑白噪声 高斯噪声 噪声的灰度值符合高斯分布 图像平滑简介 均值滤波 cv.blur(src,ksize,anchor,borderType)import numpy as np import cv2 as cv import matplotlib.…

matlab使用教程(15)—图论基础

1.有向图和无向图 1.1什么是图&#xff1f; 图是表示各种关系的节点和边的集合&#xff1a; • 节点 是与对象对应的顶点。 • 边 是对象之间的连接。 • 图的边有时会有权重 &#xff0c;表示节点之间的每个连接的强度&#xff08;或一些其他属性&#xff09;。 这些定…

【Vue-Router】使用 prams 路由传参失效

报错信息&#xff1a; [Vue Router warn]: Discarded invalid param(s) “name”, “price”, “id” when navigating. list.json {"data": [{"name": "面","price":300,"id": 1},{"name": "水",&quo…

【力扣每日一题】617. 合并二叉树 dfs bfs 8.14打卡

文章目录 题目思路代码 题目 617. 合并二叉树 难度&#xff1a; 简单 描述&#xff1a; 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff0…

AIGC热潮涌动 HashData如何降低大模型应用门槛?

当前&#xff0c;以ChatGPT为代表的大语言模型&#xff08;LLM&#xff09;正在掀起新一轮的AI 浪潮&#xff0c;数字产业生态也迎来前所未有的变局。随着大模型应用的兴起&#xff0c;如何低成本地实现大模型的构建和应用&#xff0c;成为企业关注的重点。 数据仓库是企业数据…

网络安全--筛选给定范围内的日志

目录 pass&#xff1a;在观看此篇前先看上篇的awk介绍 一、文件 二、第一方法 1.步骤 ​编辑三、第二方法&#xff1a; awk内容&#xff1a; 结果&#xff1a; 四、第二要求 统计独立ip 操作步骤&#xff1a; 1.先创建文件写入一下测试内容&#xff1a; 2.书写awk代码…

Redis缓存穿透、击穿和雪崩

1、Redis缓存穿透 缓存穿透是指当用户在查询一条数据的时候&#xff0c;而此时数据库和缓存却没有关于这条数据的任何记录&#xff0c;而这条数据在缓存中没找到就会向数据库请求获取数据。用户拿不到数据时&#xff0c;就会一直发请求&#xff0c;查询数据库&#xff0c;这样…