stack和queue的学习

news2025/4/24 20:27:49

stack的介绍

stack的文档介绍

  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中顶部的元素弹出
swap()交换2个栈中的元素

来看一个不常用的函数。
请添加图片描述

  • 解释:交换2个容器适配器中的内容
  • 示例:
#include <iostream>       // std::cout
#include <stack>          // std::stack
using namespace std;
int main()
{
	stack<int> foo, bar;
	foo.push(10); 
	foo.push(20); 
	foo.push(30);

	bar.push(111); 
	bar.push(222);

	foo.swap(bar);

	cout << "size of foo: " << foo.size() << '\n';  //size of foo: 2
	cout << "size of bar: " << bar.size() << '\n';  //size of bar: 3

	return 0;
}

这里主要展示一些常用的操作函数,至于使用方法跟其它的STL一样,所以就不在演示了。


queue的介绍

queue的文档介绍

  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()将队头元素出队列

容器适配器

容器适配器(Container Adapter)是一种设计模式,它允许将一种容器类(如 std::vectorstd::liststd::deque 等)的接口适配到另一种容器类上。在C++标准模板库(STL)中,有三种容器适配器:stackqueuepriority_queue
这些适配器提供了特定的接口,使得它们可以被当作特定的数据结构来使用,而底层实际使用的是其他容器。以下是每种容器适配器的简要说明:

  1. stack(栈):它提供了后进先出(LIFO)的数据结构接口。stack 适配器通常使用 std::dequestd::vector 作为底层容器。
  2. queue(队列):它提供了先进先出(FIFO)的数据结构接口。queue 适配器通常使用 std::deque 作为底层容器。
  3. priority_queue(优先队列):它提供了一个优先级队列的接口,其中元素按照优先级顺序排列,最高优先级的元素最先被移除。priority_queue 适配器通常使用 std::vector 作为底层容器,并使用堆(heap)数据结构来维护元素的顺序。

容器适配器的优点包括:

  • 封装性:它们隐藏了底层容器的具体实现细节,使得用户可以专注于使用特定的数据结构口。
  • 灵活性:通过改变底层容器,可以轻松地改变容器适配器的行为。
  • 一致性:它们遵循STL的一致性原则,使得代码更加模块化和可重用

stack和queue的模拟实现

stack的模拟实现

先来看看栈的基本结构

template<class T>
	class stack
	{
	private:
		vector<int> _con;
	}_

这个结构的成员_con的类型是vector<int>,后续对stack进行操作,实际上就是对vector进行操作。在进行操作之前,我们要先想清楚用vector的头部还是尾部来做栈的顶部,答案是用vector的尾部来做栈的顶。因为当在头部进行插入或者删除数据时,其它元素也会跟着移动,这会降低程序的性能。所以用尾部是最合适的。
入栈:就是对vector尾插

void push(const T& x)
{
	_con.push_back(x);
}

出栈:就是对vector尾删

void pop()
{
	_con.pop_back();
}

取栈顶:就是对vector取尾部元素

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

判空和元素个数:跟vector的操作一样

void empty()
{
	_con.empty();
}

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

那么在上面既然讲到了容器适配器,就说明还能使用其它的容器来对stack进行操作。比如说用list进行操作的话,难道还需要重新写一个list<int>的版本吗?那肯定是不需要的,只需要传入第二个参数就行了,如下所示:

template<class T,class Container = vector<T>>
	class stack
	{
	private:
		Container _con;
	}

第二个参数Container的底层容器就是默认用vector实现的,如果不传入第二个参数就默认为vector。如果想用list容器来实现stack,形式如下:
stack<int, list<int>>


queue的模拟实现
这里就直接展示代码了,跟stack的原理一样。不过queue的实现使用list比较合适,因为queue需要头删,使用list进行头删代价比较小,而且vector没有头删,只有指定删除位置上的元素,代价比较大,而list有头删,所以使用list是最合适的。

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

void push(const T& x)
{
	_con.push_back(x);
}

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

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

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

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

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

private:
		Container _con;
	};

deque的简单介绍(了解)

deque的原理

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

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

如果想头插或者尾插元素,插入的顺序就如下图所示:
请添加图片描述

可以看到,我们进行头部插入,不会影响其他数据,这是它相对于vector的优势。而由于其内存是部分连续的,可以通过中控数组的指针偏移量与小数组的指针偏移量来锁定元素。所以其也可以支持下标随机访问。

deque的优缺点

优点:

  1. 两端快速插入和删除std::deque允许在队列的前端和后端进行快速的插入和删除操作,这比std::vectorstd::list更有优势。
  2. 内存分配std::deque使用多个固定大小的块来存储元素,这可以减少内存分配和复制操作,特别是在频繁插入和删除时。
  3. 随机访问:与std::list不同,std::deque提供了随机访问迭代器,这意味着可以快速访问任何元素,就像std::vector一样。
  4. 灵活性std::deque结合了std::vector的随机访问特性和std::list的快速两端操作特性。
    缺点:
  5. 内存使用:由于std::deque使用多个块来存储元素,它可能会比std::vector使用更多的内存,因为每个块之间需要额外的空间来存储块的指针。
  6. 连续性:与std::vector不同,std::deque中的元素不是存储在连续的内存块中的,这可能会影响某些算法的性能。
  7. 迭代器失效:在std::deque中,除了在两端进行操作外,其他插入和删除操作可能会导致迭代器失效。

另外,deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构


deque与vector和list的区别

dequevectorlist
内存分配非连续内存分配,使用多个块连续内存分配,适合随机访问节点链表,每个节点包含数据和指向前后指针的节点
插入和删除性能在两端插入和删除元素时非常高效在中间插入和删除元素时,可能需要移动大量的元素在任意位置插入和删除元素时都非常高效
随机访问支持随机访问支持随机访问不支持随机访问,只能顺序访问
内存局部性由于使用多个块,内存局部性不如vector由于元素存储在连续内存中,具有很好的内存局部性不支持随机访问,只能顺序访问
迭代器失效在中间插入或删除元素时,可能会使所有迭代器失效在中间插入或删除元素时,可能会使部分迭代器失效
在任何位置插入或删除元素,都不会使迭代器失效

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

deque的使用

deque的文档介绍
请添加图片描述

  • 示例:
#include <iostream>  
#include <deque>  
  
int main ()  
{  
    unsigned int i;  
        // constructors used in the same order as described above:  
    deque<int> first;                                // 空的队列  
    deque<int> second (4,100);                       // 初始化为4个100的second队列 
    deque<int> third (second.begin(),second.end());  // 迭代器区间 
    deque<int> fourth (third);                       // 复制third 
        // the iterator constructor can be used to copy arrays:  
    int myints[] = {16,2,77,29};  
    deque<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );  
    cout << "The contents of fifth are:";  
    for (deque<int>::iterator it = fifth.begin(); it!=fifth.end(); ++it)  
        cout << ' ' << *it;  //The contents of fifth are: 16 2 77 29
    cout << '\n';  
        return 0;  
}

下面直接展示deque的函数,就不介绍使用方法
请添加图片描述
请添加图片描述
请添加图片描述

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

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

相关文章

微服务Nacos组件的介绍、安装、使用

微服务Nacos组件的介绍、安装、使用 在微服务架构日渐普及的今天&#xff0c;服务注册与配置管理成了系统架构中的关键环节。阿里巴巴开源的 Nacos&#xff08;Naming and Configuration Service&#xff09;正是解决这一问题的利器。本文将为你全面介绍 Nacos 的概念、安装方…

SpringBoot_为何需要SpringBoot?

Spring Boot 出现前的开发困境 配置繁琐 大量的 XML 配置文件 Spring 是一个非常优秀的轻量级框架&#xff0c;但其配置却是重量级的需要编写大量的 XML 配置文件或注解配置&#xff0c;使项目配置复杂且难以维护配置文件中容易出现错误&#xff0c;且排查问题困难开发过程中…

格式工厂 v5.18最新免安装绿色便携版

前言 用它来转视频的时候&#xff0c;还能顺便给那些有点小瑕疵的视频修修补补&#xff0c;保证转出来的视频质量杠杠的。更厉害的是&#xff0c;它不只是转换那么简单&#xff0c;还能帮你把PDF合并成一本小册子&#xff0c;视频也能合并成大片&#xff0c;还能随心所欲地裁剪…

MQTTX + MCP:MQTT 客户端秒变物联网 Agent

引言&#xff1a;MQTTX 与 MCP 的融合 作为最受欢迎的 MQTT 客户端工具&#xff0c;MQTTX 在 1.12.0 beta 版本中集成了模型上下文协议&#xff08;MCP&#xff09;到 Copilot AI 功能中&#xff0c;显著提升了服务能力。这一融合让 MQTTX 转变为 MCP Host&#xff08;也就是发…

快手砍掉本地生活的门槛

一场本地商家的效率革命。 作者|景行 编辑|杨舟 “两斤鸡翅根七块九&#xff0c;两盒蓝莓九块钱&#xff0c;两公斤卫生纸十四块九一提。” 这是朝阳佳惠超市&#xff0c;在快手一则普通的短视频内容。 佳惠超市在辽宁省朝阳市有22家分店&#xff0c;打开佳惠超市的相关快手…

Python基础语法3

目录 1、函数 1.1、语法格式 1.2、函数返回值 1.3、变量作用域 1.4、执行过程 1.5、链式调用 1.6、嵌套调用 1.7、函数递归 1.8、参数默认值 1.9、关键字参数 2、列表 2.1、创建列表 2.2、下标访问 2.3、切片操作 2.4、遍历列表元素 2.5、新增元素 2.6、查找元…

【AI】Windows环境安装SPAR3D单图三维重建心得

效果一览 左图为原始单个图像&#xff0c;右图为通过SPAR3D重建后的三维建模&#xff0c;可以看出效果还是不错的。 本地环境配置 系统&#xff1a;Windows 11 专业版CPU&#xff1a;i5-13400F内存&#xff1a;32GBGPU&#xff1a;RTX3060 12GBcuda&#xff1a;11.8conda&…

使用docker在manjaro linux系统上运行windows和ubuntu

因为最近项目必须要使用指定版本的solidworks和maxwell&#xff08;都只能在win系统上使用&#xff09;, 且目前的ubuntu容器是没有桌面的&#xff0c;导致我运行不了一些带图形的ros2功能。无奈之下&#xff0c;决定使用docker-compose写一下配置文件&#xff0c;彻底解决问题…

Redis(01)Redis连接报错Redis is running in protected mode……的解决方案

一、引言&#xff1a;从一个典型连接错误说起 在分布式系统开发中&#xff0c;Redis 作为高性能缓存中间件被广泛使用。 然而&#xff0c;当我们首次部署 Redis 并尝试从外部客户端连接时&#xff0c;常常会遇到以下错误&#xff1a; DENIED Redis is running in protected m…

18487.1-2015-解读笔记之四-交流充电之流程分析

前面简单分析了国标交流充电桩插枪监测逻辑和PWM控制逻辑&#xff0c;下面简单分析一下交流充电流程 附录A 交流充电连接过程和控制时序如下&#xff1a; 由此可以将充电流程大概分为几个阶段&#xff1a; 1.充电连接阶段 充电连接阶段CC&#xff08;电阻由无穷大到R4RC&…

Linux 管道理解

一、什么是管道 1.1 unix中最古老的进程间通信 1.2 一个进程链接到另一个进程的数据流称为“管道”&#xff1a; 图解&#xff1a; 二、管道通信的原理 2.1当我们创建一个进程然后打开一个文件的时候 会经过以下步骤&#xff1a; ①首先要描述这个进程&#xff0c;为这个…

国产RK3568+FPGA以 ‌“实时控制+高精度采集+灵活扩展”‌ 为核心的解决方案

RK3568FPGA方案在工业领域应用的核心优势 一、‌实时性与低延迟控制‌ ‌AMP架构与GPIO中断技术‌ 通过非对称多处理架构&#xff08;AMP&#xff09;实现Linux与实时操作系统&#xff08;RTOS/裸机&#xff09;协同&#xff0c;主核负责调度&#xff0c;从核通过GPIO中断响应紧…

Pycharm(十五)面向对象程序设计基础

目录 一、面向对象基本概述 class 类名: 属性(类似于定义变量) 行为(类似于定义函数,只不过第一个形参要写self) 二、self关键字介绍 三、在类内部调用类中的函数 四、属性的定义和调用 五、魔法方法init方法 六、魔法方法str和del方法 七、案例-减肥 一、…

华三(H3C)与华为(Huawei)设备配置IPsec VPN的详细说明,涵盖配置流程、参数设置及常见问题处理

以下是针对华三&#xff08;H3C&#xff09;与华为&#xff08;Huawei&#xff09;设备配置IPsec VPN的详细说明&#xff0c;涵盖配置流程、参数设置及常见问题处理&#xff1a; 一、华三&#xff08;H3C&#xff09;设备IPsec VPN配置详解 1. 配置流程 华三IPsec VPN配置主要…

店匠科技摘得 36 氪“2025 AI Partner 创新大奖”

全场景 AI 方案驱动跨境电商数智化跃迁 4 月 18 日,36 氪 2025 AI Partner 大会于上海盛大开幕。大会紧扣“Super App 来了”主题,全力探寻 AI 时代的全新变量,探索 AI 领域下一个超级应用的无限可能性。在此次大会上,跨境电商独立站 SaaS 平台店匠科技(Shoplazza)凭借“店匠跨…

Joint communication and state sensing under logarithmic loss

摘要——我们研究一种基本的联合通信与感知设置&#xff0c;其中发射机希望向接收机传输一条消息&#xff0c;并同时通过广义反馈估计其信道状态。我们假设感知目标是获得状态的软估计&#xff08;即概率分布&#xff09;&#xff0c;而非通常假设的点估计&#xff1b;并且我们…

Linux:41线程控制lesson29

1.线程的优点&#xff1a; • 创建⼀个新线程的代价要⽐创建⼀个新进程⼩得多 创建好线程只要调度就好了 • 与进程之间的切换相⽐&#xff0c;线程之间的切换需要操作系统做的⼯作要少很多 为什么&#xff1f; ◦ 最主要的区别是线程的切换虚拟内存空间依然是相同的&#x…

HTMLCSS实现网页轮播图

网页中轮播图区域的实现与解析 在现代网页设计中&#xff0c;轮播图是一种常见且实用的元素&#xff0c;能够在有限的空间内展示多个内容&#xff0c;吸引用户的注意力。下面将对上述代码中轮播图区域的实现方式进行详细介绍。 一、HTML 结构 <div class"carousel-c…

Java基础第21天-正则表达式

正则表达式是对字符串执行模式匹配的技术 如果想灵活的运用正则表达式&#xff0c;必须了解其中各种元字符的功能&#xff0c;元字符从功能上大致分为&#xff1a; 限定符选择匹配符分组组合和反向引用符特殊字符字符匹配符定位符 转义号\\:在我们使用正则表达式去检索某些特…

CSGO 盲盒开箱系统技术实现深度解析

一、系统架构设计 &#xff08;一&#xff09;前后端分离架构 采用前后端分离模式&#xff0c;后端专注业务逻辑处理与数据管理&#xff0c;前端负责用户交互界面呈现。后端通过 RESTful API 与前端进行数据交互&#xff0c;这种架构能有效提高开发效率&#xff0c;便于团队分…