【C++】STL详解(七)—— stack和queue的使用及模拟实现

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:C++学习
🎯长路漫漫浩浩,万事皆有期待

上一篇博客:【C++】STL详解(六)—— list的模拟实现

文章目录

  • 容器适配器
    • 什么是适配器
    • 为什么选择deque作为stack和queue的底层默认容器
  • stack
    • stack的定义方式
    • stack的使用
  • queue
    • queue的定义方式
    • queue的使用
  • stack的模拟实现
  • queue的模拟实现
  • 总结:

容器适配器

什么是适配器

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

在这里插入图片描述

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

在这里插入图片描述

在stack和queue的类模板声明当中我们就可以看到,它们的模板参数有两个,第一个是stack和queue当中所存储的元素类型,而另一个就是指定使用的容器类型。只不过当我们不指定使用何种容器的情况下,stack和queue都默认使用deque作为指定容器。

在这里插入图片描述

学过数据结构后知道,stack和queue既可以使用顺序表实现,也可以使用链表实现。在这里我们若是定义一个stack,并指定使用vector容器,则定义出来的stack实际上就是对vector容器进行了包装

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不仅效率高,而且内存使用率高。

在这里插入图片描述

stack

stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其只能从容器的一端进行元素的插入与提取操作。
在这里插入图片描述

stack的定义方式

方式一: 使用默认的适配器定义栈。

stack<int> st1;

方式二: 使用特定的适配器定义栈。

stack<int, vector<int>> st2;
stack<int, list<int>> st3;

注意: 如果没有为stack指定特定的底层容器,默认情况下使用deque。

stack的使用

stack当中常用的成员函数如下:

成员函数	 功能
empty	判断栈是否为空
size	获取栈中有效元素个数
top   	获取栈顶元素
push	元素入栈
pop 	元素出栈
swap	交换两个栈中的数据

示例:

#include <iostream>
#include <vector>
#include <stack>
using namespace std;int main()
{stack<int, vector<int>> st;st.push(1);st.push(2);st.push(3);st.push(4);cout << st.size() << endl; //4while (!st.empty()){cout << st.top() << " ";st.pop();}cout << endl; //4 3 2 1return 0;
}

queue

队列是一种容器适配器,专门用在具有先进先出操作的上下文环境中,其只能从容器的一端插入元素,另一端提取元素。
在这里插入图片描述

queue的定义方式

方式一: 使用默认的适配器定义队列。

queue<int> q1;

方式二: 使用特定的适配器定义队列。

queue<int, vector<int>> q2;
queue<int, list<int>> q3;

注意: 如果没有为queue指定特定的底层容器,默认情况下使用deque。

queue的使用

queue当中常用的成员函数如下:

成员函数	功能
empty	判断队列是否为空
size	获取队列中有效元素个数
front	获取队头元素
back	获取队尾元素
push	队尾入队列
pop	    队头出队列
swap	交换两个队列中的数据

示例:

#include <iostream>
#include <list>
#include <queue>
using namespace std;int main()
{queue<int, list<int>> q;q.push(1);q.push(2);q.push(3);q.push(4);cout << q.size() << endl; //4while (!q.empty()){cout << q.front() << " ";q.pop();}cout << endl; //1 2 3 4return 0;
}

stack的模拟实现

知道了容器适配器后,stack的模拟实现就显得相当简单,我们只需要调用所指定容器的各个成员函数即可实现stack的各个函数接口。

成员函数函数作用实现方法
push元素入栈调用所指定容器的push_back
pop元素出栈调用所指定容器的pop_back
top获取栈顶元素调用所指定容器的back
size获取栈中有效元素个数调用所指定容器的size
empty判断栈是否为空调用所指定容器的empty
swap交换两个栈中的数据调用所指定容器的swap

实现代码如下:

namespace sherry //防止命名冲突
{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();}//获取栈顶元素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();}//交换两个栈中的数据void swap(stack<T, Container>& st){_con.swap(st._con);}private:Container _con;};
}

queue的模拟实现

同样的方式,我们也是通过调用所指定容器的各个成员函数来实现queue的。

成员函数函数作用实现方法
push队尾入队列调用所指定容器的push_back
pop队头出队列调用所指定容器的pop_front
front获取队头元素调用所指定容器的front
back获取队尾元素调用所指定容器的back
size获取栈中有效元素个数调用所指定容器的size
empty判断栈是否为空调用所指定容器的empty
swap交换两个队列中的数据调用所指定容器的swap

实现代码如下:

namespace sherry //防止命名冲突
{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();}//获取队头元素T& front(){return _con.front();}const T& front() const{return _con.front();}//获取队尾元素T& back(){return _con.back();}const T& back() const{return _con.back();}//获取队列中有效元素个数size_t size() const{return _con.size();}//判断队列是否为空bool empty() const{return _con.empty();}//交换两个队列中的数据void swap(queue<T, Container>& q){_con.swap(q._con);}private:Container _con;};
}

总结:

今天我们比较详细地完成了stack和queue的使用及模拟实现,了解了一些有关的底层原理。接下来,我们将进行STL中priority_queue的学习。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

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

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

相关文章

跨域问题解决方案(三种)

Same Origin Policy同源策略&#xff08;SOP&#xff09; 具有相同的Origin&#xff0c;也即是拥有相同的协议、主机地址以及端口。一旦这三项数据中有一项不同&#xff0c;那么该资源就将被认为是从不同的Origin得来的&#xff0c;进而不被允许访问。 Cross-origin resource…

strtok()函数的使用方法

strtok() 函数用于将字符串分割成子字符串&#xff08;标记&#xff09;。它在 C 语言中非常常用&#xff0c;可以通过指定分隔符来拆分原始字符串&#xff0c;并依次返回每个子字符串。 以下是 strtok() 函数的使用方法&#xff1a; #include <stdio.h> #include <…

JUC第七讲:关键字final详解

JUC第七讲&#xff1a;关键字final详解 final 关键字看上去简单&#xff0c;但是真正深入理解的人可以说少之又少。本文是JUC第七讲&#xff1a;关键字final详解&#xff0c;将常规的用法简化&#xff0c;提出一些用法和深入的思考。 文章目录 JUC第七讲&#xff1a;关键字fina…

光伏发电系统最大功率跟踪控制MATLAB仿真模型(电导增量法+扰动观察法)

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型介绍&#xff1a; 模型主要包含光伏电池模块、直流升压模块、以及最大功率跟踪控制模块。 扰动观察法&#xff08; P&O &#xff09;&#xff1a; 所谓 P&O 就是每过一会给予系统工作电压一个可…

【C++】C++11——可变参数模板和emplace

可变参数模板的定义方式可变参数模板的传值计算可变参数模板参数个数参数包展开方式递归展开参数包逗号表达式展开参数包 emplace插入 可变参数模板是C11新增的最强大的特性之一&#xff0c;它对参数高度泛化&#xff0c;能够让我们创建可以接受可变参数的函数模板和类模板。 在…

【Less-CSS】初识Less,使编写 CSS 变得简洁

初识Less&#xff0c;使编写 CSS 变得简洁 1.Less简述2.LESS 原理及使用方式3.示例4.less语法5.Easy Less插件 作为一门标记性语言&#xff0c;CSS 的语法相对简单&#xff0c;对使用者的要求较低&#xff0c;但同时也带来一些问题&#xff1a;CSS 需要书写大量看似没有逻辑的代…

软件项目测试用例评审

软件项目测试用例评审是确保测试计划的一部分&#xff08;即测试用例&#xff09;满足项目质量和要求的关键步骤之一。以下是一个通用的软件项目测试用例评审流程&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎…

Prometheus+Grafana可视化监控【Redis状态】

文章目录 一、安装Docker二、安装Redis数据库(Docker容器方式)三、安装Prometheus四、安装Grafana五、Pronetheus和Grafana相关联六、安装redis_exporter七、Grafana添加Redis监控模板 一、安装Docker 注意&#xff1a;我这里使用之前写好脚本进行安装Docker&#xff0c;如果已…

计网第五章(运输层)(八)(TCP的连接释放)

目录 一、基本概述 二、具体实现 三、经典问题之为什么客户进程不直接进入关闭状态&#xff1f; 四、保活计时器 一、基本概述 上篇博客&#xff08; 计网第五章&#xff08;运输层&#xff09;&#xff08;七&#xff09;&#xff08;TCP的连接建立&#xff09;&#xff…

Wiki.js - 下一代的开源Wiki软件

简介&#xff1a;在众多开源的Wiki软件中&#xff0c;Wiki.js无疑是一个独特且现代的选择。基于Node.js构建&#xff0c;使用了最新的Web技术&#xff0c;Wiki.js为用户提供了一个美观且功能丰富的界面&#xff0c;同时还保留了强大的扩展性和自定义性。无论你是为个人、团队或…

硬件故障诊断:快速定位问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…

Java IO流实现文件复制

目录 前言 文件复制底层逻辑 代码实现 ​编辑 重点&#xff01;&#xff01;&#xff01; 完整代码 改善思考 前言 Windows文件复制时我们是使用Ctrl C复制Ctrl V粘贴&#xff0c;上一篇文章Java基础入门对存储文件的相关操作 我们学习了Java IO流对文件的读写操作&…

uploadifive上传工具php版使用

uploadifive自带的DEMO文件。 下载地址&#xff1a; http://www.uploadify.com/download/ <!DOCTYPE HTML> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"> <title>UploadiFive Test&…

MQ - 24 Pulsar集群架构设计与实现

文章目录 导图概述集群构建主节点弱 ZooKeeper 实现数据可靠性安全控制传输加密端到端加密身份认证资源鉴权可观测性总结导图 概述 从设计定位上来看,Pulsar 是作为 Kafka 的升级替代品出现的,它主要解决了 Kafka 在集群层面的弹性和规模限制问题。那么现在我们就从集群的角…

STM32实现PMBus从机程序

最近在野火的STM32F103VET6开发板上实现PMBus从机程序&#xff0c;这个程序参考了以下这篇博客的关于使用中断法实现I2C从机程序&#xff1a;STM32设置为I2C从机模式_iic从机_柒壹漆的博客-CSDN博客 &#xff0c;实测这个程序是可以正常运行的&#xff0c;感谢博主的分享&#…

3.wifi开发,网络编程

网络协议栈LwIP WiFi UDP Clinet编程 WiFi UDP Server编程 WiFi TCP Client编程 WiFi TCP Server编程 一。LWIP原理介绍&#xff0c;API介绍&#xff0c;文件结构 1.Lwip支持的协议 2.API 3.文件结构 1.api目录&#xff1a;应用程序接口文件。 2.arch目录&#xff1a;与硬件和…

k8s master 是如何进行pod的调度的

Master 节点将 Pod 调度到指定的 Node 节点的原理 该工作由 kube-scheduler 来完成&#xff0c;整个调度过程通过执行一些列复杂的算法最终为每个 Pod 计算出一个最佳的目标 Node&#xff0c;该过程由 kube-scheduler 进程自动完成。常见的有轮询调度&#xff08;RR&#xff09…

Chrome浏览器删除网站cookies的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

[论文笔记]P-tuning v2

引言 今天带来第五篇大模型微调论文笔记P-tuning v2: Prompt Tuning Can Be Comparable to Fine-tuning Across Scales and Tasks。 作者首先指出了prompt tuning的一些不足,比如在中等规模的模型上NLU任务表现不好,还不能处理困难的序列标记任务,缺乏统一应用的能力。 然…

安卓系统--翻译手机rom语言 添加多国语言 编译apk 反编译ODEX 工具步骤解析

很多小品牌机型不具备多语言设置。国内大都是中文。要想换为其他语言除非固件支持。例如国际版固件等等。大厂基本都有中文或者英文或者其他语言配置。而小品牌机型只能通过修改rom来达到多语言调用. 工具步骤演示 今天给友友介绍一款工具&#xff0c;可以用来翻译手机rom语言…