【C++】STL——stack和queue

目录

  • 前言
  • 容器配接器(适配器)
  • stack的使用
  • stack的模拟实现
  • queue的使用
  • queue的模拟实现
  • 双端队列(deque)

请添加图片描述

前言

前面我们已经学习了STL容器中的string、vector还有list。

【C++】string的模拟实现
【C++】STL——vector的模拟实现
【C++】STL——list的模拟实现

下面我们来学习stack和queue。
在这里插入图片描述
  但是我们由STL这张图可以看出,stcak和queue并不在容器中,而是在配接器中。什么是配接器,下面来讲解一下。

容器配接器(适配器)

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

具体了解可看:百度百科——适配器

在这里插入图片描述
  所以实际上,适配器的本质就是转换,把原始接口转换为客户想要的就行。
  stack和queue中也可以存放元素,但STL中并没有将其放在容器中,而是将其称为容器适配器,是因为stackqueue只是对其他容器的接口进行了包装,而这个其他容器,在STL中默认使用的是deque(双端队列,后面会稍微讲解一下).
库里面对stack和queue的定义如下:
在这里插入图片描述
在这里插入图片描述

  可以看出,stack和queue都使用了deque,将其进行了包装,就转换成了栈和队列。

stack的使用

  stack是一种容器适配器,专门设计用于在 LIFO (后进先出)上下文中运行,其中元素仅从容器的一端插入和提取。

  stack的底层容器可以是任何标准的容器类模板或者其他一些特定的容器类,这些容器应支持以下操作:

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

  标准容器vector、deque、list均符合这些要求,默认情况下,如果没有为stack指定特定底层容器,默认使用deque(双端队列)。
stack的使用接口并不多,就如下几个:

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

一个简单的使用样例给到大家参考:

#include<iostream>
#include<list>
#include<deque>
#include<stack>
using namespace std;

int main()
{
	stack<int> s;//不写底层容器默认给deque
	stack<int, list<int>> sl;
	stack<int, deque<int>> sd;
	//使用typeid可以查看类型
	cout << typeid(s).name() << endl;
	cout << typeid(sl).name() << endl;
	cout << typeid(sd).name() << endl;

	s.push(1);
	s.push(2);
	s.push(3);

	cout << "s.size():" << s.size() << endl;
	cout << "s中的元素有:";
	while (!s.empty())
	{
		cout << s.top() << " ";
		s.pop();
	}

	return 0;
}

结果如下:
在这里插入图片描述

stack的模拟实现

在这里插入图片描述
在这里插入图片描述

模拟实现也比较简单:

namespace bit
{
	template<class T,class Container = deque<T>>
	class stack
	{
		//默认成员函数都不用自己去写,用底层容器默认生成的即可
	public:
		void push(const T& x)
		{
			_con.push_back(x);
		}
		void pop()
		{
			_con.pop_back();
		}
		T& top()
		{
			return _con.back();
		}
		const T& top() const
		{
			return _con.back();
		}
		size_t size() const
		{
			return _con.size();
		}
		bool empty() const
		{
			return _con.empty();
		}
	private:
		Container _con;
	};

  我们发现,stack私有成员变量就是一个底层容器,而stack类的所有默认成员函数都不用自己写,都直接调用底层容器的默认成员函数即可,包括其他函数的实现,我不需要去管,因为底层容器已经实现好了,我们只需调用即可,这就是容器适配器的好用之处。

queue的使用

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

  • empty:判空操作
  • size:获取队列中有效元素个数
  • front:返回队头元素的引用
  • back:返回队尾元素的引用
  • push_back:在队列尾部如队列
  • pop_back:在队列头部出队列

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

list的使用和stack完全一致,接口也就这几个:

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

使用样例如下:

#include<iostream>
#include<list>
#include<deque>
#include<queue>

using namespace std;

int main()
{
	queue<int> q;//不写底层容器默认给deque
	queue<int, list<int>> ql;
	queue<int, deque<int>> qd;
	//使用typeid可以查看类型
	cout << typeid(q).name() << endl;
	cout << typeid(ql).name() << endl;
	cout << typeid(qd).name() << endl;

	q.push(1);
	q.push(2);
	q.push(3);

	cout << "s.size():" << q.size() << endl;
	cout << "队尾元素:" << q.back() << endl;
	cout << "s中的元素有:";
	while (!q.empty())
	{
		cout << q.front() << " ";
		q.pop();
	}

	return 0;
}

queue的模拟实现

queue的模拟实现和stack类似,同样通过模板和底层容器deque来实现:

namespace bit
{
	template<class T, class Container = deque<T>>
	class queue
	{
	public:
		bool empty() const
		{
			return _con.empty();
		}
		size_t size() const
		{
			return _con.size();
		}
		T& front()
		{
			return _con.front();
		}
		const T& front() const
		{
			return _con.front();
		}
		T& back()
		{
			return _con.back();
		}
		const T& back()
		{
			return _con.back();
		}
		void pop()
		{
			return _con.pop_front();
		}
		void push()
		{
			return _con.push_back;
		}
	private:
		Container _con;
	};
}

要注意函数之间的调用:

  1. queue中的pop函数要调用deque的pop_front删除第一个元素的函数
  2. queue中的push函数要调用deque的push_back尾插函数

双端队列(deque)

通过几张图来简单瞧一瞧双端队列:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  对于双端队列中间的各种操作我们不再细说,我们直接来说一说deque的优点和缺陷
优点

  • 与vector比较头插头删不需要搬移元素效率较高,扩容也不需要搬移大量元素。
  • 与List比较,底层是连续的空间,空间利用率高

缺陷:不适合遍历。

所以选择deque作为stack和queue的底层默认容器主要原因为

  1. stack和queue不需要遍历
  2. stack元素增长时,deque比vector的效率高(不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。
    结合了deque的优点,且完美避开了缺点。

感谢大家观看,如果大家喜欢,希望大家一键三连支持一下,如有表述不正确,也欢迎大家批评指正。
请添加图片描述

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

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

相关文章

CTF-PWN方向 栈溢出等基础知识笔记(2)

ret2syscall 要求有0x80这种系统调用存在 &#xff08;0x0A是回车的意思&#xff09; 案例 通过file查看这个文件 发现是静态编译的文件 所以很多库函数都被编译进去了 但是不存在bin/sh字符串 不存在system和backdoor函数 系统调用需要用到的寄存器 通过ROPgadget工具来查找…

传统图像处理Opencv分割不同颜色的夹子

任务要求&#x1f349; 1. 计算图像中夹子的总数。 2. 分别计算不同颜色夹子的个数。 3. 使用以下方法适应三张图片&#xff0c;并在每张图像上显示结果&#xff1a; - 阈值方法 - HSV颜色空间 - 连通域分析 - 形态学图像处理 - Canny边缘检测 4. 在结果中显示计…

《数据密集型应用系统设计》笔记——第二部分 分布式数据系统(ch5-9)

第5章 数据复制 目的&#xff1a; 地理位置更近&#xff0c;降低延迟故障冗余提高读吞吐量 主节点与从节点&#xff08;主从复制&#xff09; 主从复制&#xff1a; 写请求发送给主节点&#xff0c;主节点将新数据写入本地存储&#xff1b;主节点将数据更改作为复制的日志发送…

使用java做一个微信机器人

微信机器人这个功能&#xff0c;目前在市面上运用的还是不是很多&#xff0c;每个人实现机器人的目的也不一样&#xff0c;有的为了自动加好友;有的为了自动拉群:也有的为了机器人对话聊天等等一系列。想必大家对微信机器人感兴趣的伙伴&#xff0c;但是大多数走到一半遇到各种…

Android Jetpack Compose中UI刷新的几种方式

Android Jetpack Compose中UI刷新的几种方式 在 Jetpack Compose 中,如果你想强制刷新 UI,可以使用 remember 和 mutableStateOf 来创建一个可观察的状态。当这个状态变化时,Compose 会自动重组 UI。以下是一些常见的方法来实现这一点: 1. 使用 mutableStateOf 你可以使…

[SQL] 安装

一 Windows 1.1 下载 进入Mysql的官方网站,点击下载->找到社区版本 选择对应操作系统进行下载。 点击下载 选择直接下载即可 1.2 安装 选择Full安装&#xff1a; MySQL服务器、客户端程序和其他附加工具如果只需要服务端那就选择Server only即可 点击执行,等待组件下载完…

【Unity踩坑】UWP项目安装包认证失败

问题&#xff1a;在Unity导出的VS项目&#xff0c;打包生成appx后&#xff0c;进行应用认证时失败。提示部分API不支持。 API __C_specific_handler in kernel32.dll is not supported for this application type. UnityPlayer.dll calls this API.API DXGIGetDebugInterface1 …

Windows 搭建 Gitea

一、准备工作 1. 安装 Git&#xff1a;Gitea 依赖 Git 进行代码管理&#xff0c;所以首先需要确保系统中安装了 Git。 下载地址&#xff1a;https://git-scm.com/downloads/win 2. 安装数据库&#xff08;可选&#xff09; 默认情况下&#xff0c;Gitea 使用 SQLite 作为内…

k8s部署学习

8s的架构 一个kubernetes集群主要是由控制节点(master)、工作节点(node)构成&#xff0c;每个节点上都会安装不同的组件 1 master&#xff1a;集群的控制平面&#xff0c;负责集群的决策 ApiServer : 资源操作的唯一入口&#xff0c;接收用户输入的命令&#xff0c;提供认证、…

【每天学点AI】大模型如何做情感分类?BERT是如何做情感分类的?

BERT是如何做情感分类的呢&#xff1f;今天&#xff0c;让我们一起揭开BERT模型的神秘面纱&#xff0c;看看它是如何巧妙地进行情感分类的&#xff01; BERT&#xff0c;作为一个双向编码器模型&#xff0c;它的独特之处在于能够全面吸收一段文本或句子的精髓。 通过tokenizer…

五款专业三维数据处理工具:GISBox、Cesiumlab、OSGBLab、灵易智模、倾斜伴侣深度解析

随着三维数据处理技术的广泛应用&#xff0c;尤其是在城市规划、地理信息系统&#xff08;GIS&#xff09;、工程监测等领域&#xff0c;处理倾斜摄影、三维建模以及大规模数据管理的需求日益增加。以下是五款我精心挑选的倾斜摄影和三维数据处理工具——GISBox、Cesiumlab、OS…

Kubernetes(K8s)的简介

一、Kubernetes的简介 1 应用部署方式演变 在部署应用程序的方式上&#xff0c;主要经历了三个阶段&#xff1a; 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其它技术的参与 缺点&#xff1a;不能为应…

C语言预处理详解(下)(31)

文章目录 前言一、命令行定义二、条件编译三、文件包含头文件被包含的方式嵌套文件包含 总结 前言 再介绍几点吧&#xff01; 一、命令行定义 许多C 的编译器提供了一种能力&#xff0c;允许在命令行中定义符号。用于启动编译过程 当我们根据同一个源文件要编译出不同的一个程序…

太速科技-607-基于FMC的12收和12发的光纤子卡

基于FMC的12收和12发的光纤子卡 一、板卡概述 本卡是一个FPGA夹层卡&#xff08;FMC&#xff09;模块&#xff0c;可提供高达2个CXP模块接口&#xff0c;提供12路收&#xff0c;12路发的光纤通道。每个通道支持10Gbps,通过Aurora协议&#xff0c;可以组成X4&#xff0…

中间件介绍

可以把中间件想象成是在应用和系统之间搭建的一座桥梁&#xff0c;或者说是一个“翻译官”和“中转站”。它处在操作系统、网络和数据库之上&#xff0c;应用软件的下层&#xff0c;负责实现应用软件之间的互联互通&#xff0c;使得应用软件能够更方便、高效地进行数据交换和通…

2024最新CSDN Markdown编辑器语法教程

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

R语言中的plumber介绍

R语言中的plumber介绍 基本用法常用 API 方法1. GET 方法2. POST 方法3. 带路径参数的 GET 方法 使用 R 对数据进行操作处理 JSON 输入和输出运行 API 的其他选项其他功能 plumber 是个强大的 R 包&#xff0c;用于将 R 代码转换为 Web API&#xff0c;通过使用 plumber&#x…

cmake --build使用踩坑记录

根据 深入理解 CMake 的 cmake --build 命令_cmake build-CSDN博客等消息来源的说法&#xff0c; cmake --build <dir> 将在目录<dir>中产生结果文件。但是实测发现&#xff0c;这里有坑&#xff1a;如果目录<dir>中没有CMakeCache.txt等文件的话&#xff…

高性能缓存方案 —— Caffeine

一、简介 Caffeine是一个高性能的Java缓存库&#xff0c;它提供了本地缓存的功能。 Caffeine和Redis都是内存级别的缓存&#xff0c;为什么要使用在这两缓存作为二级缓存&#xff0c;它们两有什么区别呢? 虽然它们都是内存级别的缓存&#xff0c;但是Redis是需要单独部署的&…

RPA技术的定义与原理

RPA&#xff08;Robotic Process Automation&#xff09;即机器人流程自动化&#xff0c;是一种利用软件机器人或机器人工具来自动执行重复性、规则性和可预测性的业务流程的技术。以下是对RPA技术的详细介绍&#xff1a; 一、RPA技术的定义与原理 RPA技术通过模拟人工操作&a…