C++ STL:stack和queue的使用和底层实现

目录

一. 什么是stack和deque

二. stack和queue的使用方法

2.1 stack的常用接口

2.2 queue的常用接口

三. stack和queue的底层实现原理 

3.1 容器适配器

3.2 deque(双端队列)的概念及抽象结构

3.3 deque的底层实现结构

3.4 deque的优缺点 —— 为什么使用deque作为stack和queue的默认适配容器

3.5 通过deque容器来模拟实现stack和queue


一. 什么是stack和deque

stack是数据结构中的栈,遵循后进先出规则,queue是数据结构中的队列,遵循先进先出规则。

图1.1 栈(stack)的抽象结构图
图1.2 队列(queue)的抽象结构图

二. stack和queue的使用方法

2.1 stack的常用接口

接口函数名功能
push数据压栈
pop数据出栈
top获取栈顶元素
size获取栈中元素个数
empty检查栈是否为空
int main()
{
	stack<int> st;  //创建存储int型数据的栈

	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);   //压栈操作,依次压入1、2、3、4

	cout << "is empty:" << st.empty() << endl;  //检查栈是否为空
	cout << "size of stack:" << st.size() << endl;  //检查栈中数据个数

	st.pop();   //栈顶数据出栈
	cout << "top = " << st.top() << endl;  //获取栈顶数据

	return 0;
}

2.2 queue的常用接口

接口函数名功能
push队尾入数据
pop队头出数据
empty判断队列是否为空
size获取队列中数据个数
front获取队头数据
back获取队尾数据
int main()
{
	queue<int> q;  //创建存储int型数据的队列

	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);  //队头入数据

    cout << "is empty:" << q.empty() << endl;  //检查队列是否为空
	cout << "size of queue:" << q.size() << endl;  //检查队列中数据个数

	q.pop();  //队头数据出队列
	cout << "front = " << q.front() << endl;
	cout << "back = " << q.back() << endl;    //获取队头数据和队尾数据

	return 0;
}

三. stack和queue的底层实现原理 

3.1 容器适配器

C++ STL中给出的stack和queue类的声明为:

  • template <class T, class Container = deque<T>>  class stack;
  • template <class T, class Container = deque<T>>  class queue;

由stack和queue的声明不难发现,它们本质上并不是容器,而是容器适配器,stack和queue的底层都是调用名为deque(双端队列)的容器的接口来实现的。

所谓适配器,通俗讲就是一种设计模式,即:一套被反复使用的、为多数人所知晓的、经过分类编目的代码设计经验的总结,设计模式可以将一个类接口转换为用户希望的其它类接口。

3.2 deque(双端队列)的概念及抽象结构

deque是双端队列容器,它可以同时支持O(1)时间复杂度下的头部的插入删除和在尾部的插入和删除,同时,可以通过下标来访问任意位置处的元素。

  • 对于vector,它可以支持O(1)时间复杂度下的尾插数据和尾删数据,但要实现头插和头删则需要O(N)的时间复杂度。
  • 对于list,它可以实现在O(1)时间复杂度下任意位置的插入和删除数据,但不能支持通过下标来进行随机访问。

所以,在某种程度上,我们可以认为deque兼具了vector和list的一些优点。

图3.1 双端队列(deque)的抽象结构

3.3 deque的底层实现结构

  • 虽然在deque的抽象结构图中,数据在deque中是连续存储的。但是,deque的真是实现是在内存堆区申请一块块的小空间来存储数据的,这一块块小空间维持了deque整体连续的表象。
  • 在deque类被实例化时,首先开辟一块内存空间,向deque对象中尾插数据时,首先检查当前的小块空间是否已满,如果满,则新开辟一小块空间,在新开辟的空间中插入数据,如果不满,则直接在当前的小块空间中插入数据。
  • 在执行头插数据操作时,先检查当前小块空间的前部是否还有空间,如果有,则直接在当前空间的前部插入数据,如果没有,则新开辟一块空间,在新开辟的空间的最后一个位置插入数据。
  • 通过一个中控指针数组,来模拟拼接每一小块空间。中控指针数组中存储每一小块内存空间的地址,中控指针数组下标小的位置处记录的地址中存储的数据位于双端队列的前部,下标大的位置对应双端队列的后部。
图3.2 deque的底层结构体

3.4 deque的优缺点 —— 为什么使用deque作为stack和queue的默认适配容器

虽然deuqe兼具了vector和list的一些优点,但是,deuqe依然极少作为单独的数据结构容器来使用,而是仅仅作为stack和queue等数据结构的适配容器。

deque相对于vector的优点和缺点

  • 优点:
  1. deque支持以O(1)的时间复杂度完成头插和头删数据操作,vector如果头插和头删数据操作需要移动后面的所有数据,时间复杂度为O(N),效率相对于deque较低。
  2. deque扩容时不需要复制数据,而且deque一次开辟一小块空间,空间利用率高。而vector在扩容时需用复制已有数据到新的内存空间,并且每次扩容得到新空间的容量一般是原来容量的1.5倍或2倍,vector扩容时复制数据需要一定的消耗且空间浪费相对于deque较多。
  • 缺点:
  1. 不适合遍历和随机访问,因为deuqe在进行遍历时,迭代器需要频繁地去检查是否移动到了某一小段空间的边界位置,效率低下。

deque相对于list的优点和缺点

  • 优点:
  1. deque底层空间连续,不需要频繁地申请和释放小块的内存空间,申请和释放空间的消耗相对于list较低。
  2. 由于deque底层空间连续,CPU高速缓存命中率高。
  3. 不需要每个存储每个数据时都存储两个指针来指向前一个和后一个数据的位置。
  • 缺点:
  1. 无法在O(1)时间复杂度的下实现在中间某个位置插入和删除数据。

为什么使用deque作为stack和queue的底层适配容器

如果没有deuqe容器,那么,stack只能使用vector或list来实现,queue只能使用list来实现。

  • 相对于vector实现stack:deque的扩容代价低,扩容不用拷贝数据,空间浪费较少。
  • 相对于list实现stack:deque不用频繁申请和释放小块内存空间,CPU高速缓存命中率高,申请和释放内存空间的次数少。
  • 相对于list实现queue:deque不用频繁申请和释放小块内存空间,CPU高速缓存命中率高,申请和释放内存空间的次数少。

3.5 通过deque容器来模拟实现stack和queue

下表为deuqe所支持的常规操作,我们不难发现,deque支持stack和queue的全部操作,因此,只需要在stack和queue接口的实现中调用deque容器对应的接口,就可以完成对stack和deque的模拟实现。

deque的接口函数实现的功能
size获取数据个数
resize删除数据 或 扩容+初始化新增空间
empty判断是否为空
operator[]通过下标访问数据
push_back尾插数据
pop_back尾删数据
push_front头插数据
pop_front头删数据
insert在特定位置插入数据
erase删除特定位置的数据
clear清空数据

模式实现queue:

#include<cstdbool>
#include<deque>

namespace zhang
{
	template <class T, class Container = std::deque<T>>
	class queue
	{
	public:
		//数据入队列操作
		void push(const T& x)
		{
			_con.push_back(x);
		}

		//数据出队列操作
		void pop()
		{
			_con.pop_front();
		}

		//数据量获取函数
		size_t size() const
		{
			return _con.size();
		}

		//判空函数
		bool empty() const
		{
			return _con.empty();
		}

		//获取队头数据函数
		const T& front() const
		{
			return _con.front();
		}

		T& front()
		{
			return _con.front();
		}

		//获取队尾数据函数
		const T& back() const
		{
			return _con.back(); 
		}

		T& back()
		{
			return _con.back();
		}

	private:
		Container _con;
	};
}

模式实现stack:

#include<deque>
#include<cstdbool>

namespace zhang
{
	template <class T, class Container = std::deque<T>>
	class stack
	{
	public:
		void push(const T& x)  //压栈 -- 数据插入函数
		{
			_con.push_back(x);
		}

		void pop()   //出栈 -- 数据删除函数
		{
			_con.pop_back();
		}

		bool empty()  //判空函数
		{
			return _con.empty();
		}

		T& top()  //栈顶数据获取函数
		{
			return _con.back();
		}

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

		size_t size() const  //获取栈中数据个数
		{
			return _con.size();
		}

	private:
		Container _con;  //用于实现栈的容器
	};
}

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

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

相关文章

try... excpet BaseException(异常处理捕获)

try ...except 是最常见的捕获处理异常的结构&#xff0c;其主要作用是将可能出现问题的代码块用try &#xff1a;包裹起来&#xff0c;不至于出现错误让程序崩溃&#xff0c;无法执行下去常见的try ...excpet 的结构有三种try&#xff1a;pass except BaseException as e &…

Azure SQL基础到实战(2)-部署

目录Azure 上的数据库服务的演变Azure SQL 部署选项Azure 虚拟机上的 SQL ServerIaaS 与PaaS无版本数据库服务SQL 托管实例SQL 数据库弹性数据库池Azure 上的数据库服务的演变 Azure SQL 是 Microsoft 作为 Azure 云计算平台的一部分提供的云数据库产品/服务。 与其他版本的 S…

含光热电站、有机有机朗肯循环、P2G的综合能源优化调度(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

算法---扫雷游戏

题目 让我们一起来玩扫雷游戏&#xff01; 给你一个大小为 m x n 二维字符矩阵 board &#xff0c;表示扫雷游戏的盘面&#xff0c;其中&#xff1a; ‘M’ 代表一个 未挖出的 地雷&#xff0c; ‘E’ 代表一个 未挖出的 空方块&#xff0c; ‘B’ 代表没有相邻&#xff08;…

服务器部署前后端分离项目

服务器部署前后端分离项目 文章目录服务器部署前后端分离项目一、安装环境安装jdk1、在/usr/local目录下创建jdk文件夹&#xff0c;并将jdk安装包放到/usr/local/jdk包下并解压2、配置jdk的环境变量3、进行编译&#xff0c;4、检测是否安装成功安装tomcat1、将tomcat放到/usr/l…

Linux内核模块开发之创建slab内存缓存(kmem_cache_*)

Linux内核模块开发之创建slab内存缓存&#xff08;kmem_cache_*&#xff09;一、创建专用的内存缓存编程接口二、实现步骤三、内存缓存的数据结构四、完整代码示例4.1、源代码4.2、编译和执行一、创建专用的内存缓存编程接口 创建内存缓存 kmem_cache_create。指定内存缓存分配…

软件测试零基础好入门么

零基础学习软件测试不失为一个好的选择&#xff0c;虽然IT行业里对小白最友好的非软件测试莫属了&#xff0c;但是也要看你个人在学习软件测试这件事上面花费了多少的时间和努力了~ 每年毕业季&#xff0c;IT行业依然是比较热门且收入是最高的行业。对于应届毕业生来说想要进入…

数据结构学习之路-队列

队列&#xff08;Queue&#xff09;定义队列的接口设计&#xff08;使用双向链表&#xff09;用栈实现队列的接口设计双端队列&#xff08;Deque&#xff09;循环队列&#xff08;Circle Queue&#xff09;循环双端队列&#xff08;Ciecle Deque&#xff09;定义 队列是一种特…

企业短视频推广怎么玩?制造业短视频推广干货分享

短视频作为一种新型营销方式&#xff0c;已经成为企业推广的重要手段。通过合理的推广策略、精美的短视频制作、适当的社交媒体平台选择和与用户的互动&#xff0c;企业可以实现短视频推广的效果。同时&#xff0c;借助短视频制作工具可以提高制作效率和降低制作成本&#xff0…

文件IO知识(一)

作者&#xff1a;爱塔居 专栏&#xff1a;JavaEE 作者简介&#xff1a;大三学生&#xff0c;希望和大家一起进步。 文章目录 目录 文章目录 前言 一、路径 二、文本文件和二进制文件 三、文件系统操作 四、“字符流”和“字节流” 五、utf8和unicode 前言 平时谈到的“文件”&…

Spring 源码解析 - BeanPostProcessor 扩展接口

一、BeanPostProcessor 扩展接口 BeanPostProcessor是Spring中的一个扩展接口&#xff0c;它可以在Spring容器实例化bean之后&#xff0c;在执行 bean的初始化方法前后&#xff0c;允许我们自定义修改新的 bean实例。比如修改 bean 的属性&#xff0c;将 bean 替换为动态代理等…

《Effective Objective-C 2.0 》 阅读笔记 item6

第6条&#xff1a;理解“属性”这一概念 1. 属性的概念 “属性”&#xff08;property&#xff09;是Objective-C的一项特性&#xff0c;用于封装对象中的数据。 Objective-C对象通常会把所需要的数据保存为各种实例变量&#xff0c;实例变量一般通过“存取方法”&#xff08…

GPT-4 免费体验方法

POE 在Quora上非常受欢迎的手机聊天机器人Poe App已经集成ChatGPT助手&#xff01;除了最初集成的三个聊天机器人Sage、Claude和Dragonfly外&#xff0c;Poe现在还加入了第四位ChatGPT。由于使用了ChatGPT API&#xff0c;因此Poe拥有真正的ChatGPT。 现在更是第一批集成了GP…

JDK1.8去除永久代引入元空间的原因您知道吗

之前写了一篇文章 JVM中的堆和栈到底存储了什么 重点介绍了Java虚拟机运行时数据区中堆、栈以及方法区存储数据的相关知识很受大家欢迎&#xff0c;今天来介绍一下jdk 1.8开始引入的元空间&#xff0c;元空间的引入也是与Java虚拟机运行时存储数据有关。 元空间 JDK8之后就没…

02-Maven高级-分模块开发、依赖传递、聚合、继承(SpringBoot的部分底层原理)、多模块开发(环境切换)、Nexus私服搭建与使用

文章目录学习目标一、分模块开发与设计1. 分模块开发的意义问题导入模块拆分原则2. 分模块开发&#xff08;模块拆分&#xff09;问题导入2.1 创建Maven模块2.2 书写模块代码2.3 通过maven指令安装模块到本地仓库&#xff08;install指令&#xff09;2.4 代码演示二、依赖管理1…

高低温真空磁场探针台T8-EM5的技术参数

高低温真空磁场探针台是具备提供高低温、真空以及磁场环境的高精度实验台&#xff0c;它的诸多设计都是专用的。因此&#xff0c;高低温磁场探针台的配置主要是根据需求进行选配及设计。例如&#xff0c;要求的磁场值&#xff0c;均匀区大小、均匀度大小、样品台的尺寸等&#…

OJ系统刷题 第三篇

11202 - 任意两个数的和 时间限制 : 1 秒 内存限制 : 128 MB 编程序&#xff0c;电脑任意输入两个整数&#xff0c;计算出他们的和。 输入 a b&#xff08;a b为整数&#xff0c;范围是-2,147,483,648~2,147,483,647&#xff09; 输出 ab的和 样例 输入 1 1 输出 2 答案&a…

含分布式电源的配电网可靠性评估研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

外网访问本地Tomcat服务器【cpolar内网穿透】

文章目录前言1.本地Tomcat网页搭建1.1 Tomcat安装1.2 配置环境变量1.3 环境配置1.4 Tomcat运行测试1.5 Cpolar安装和注册2.本地网页发布2.1.Cpolar云端设置2.2 Cpolar本地设置3.公网访问测试4.结语前言 Tomcat作为一个轻量级的服务器&#xff0c;不仅名字很有趣&#xff08;让…

第二届ACC(AcWing Cup)全国联赛 C4943. 方格迷宫

题意 题目大意就是给定一个地图&#xff0c;给定一个起点和终点&#xff0c;要求我们以最小步数到达终点&#xff0c;其中不可以落入陷阱并且每步可以走1−−k步题目大意就是给定一个地图&#xff0c;给定一个起点和终点&#xff0c;要求我们以最小步数到达终点&#xff0c;其中…