C++STL之stack和queue容器(详细+通俗易懂)

前言:老铁们好,笔者好久没更新STL的容器了,今天,笔者接着之前的STL容器的内容继续更新,所以今天给老铁们分享的是STL里面的栈和队列的容器的知识。

1.栈的定义

老规矩,我们先来看看C++的官网对stack的介绍文档。
在这里插入图片描述
然后我再为老铁们用大白话解释一下文档里面的内容。

1.在数据结构那一门课程中我们就学过,栈具有后进先出的特点,数据只能从栈顶出入,文档中第一点讲的就是这个。

2.栈是作为容器适配器被实现的,什么是容器适配器呢?容器适配器就像一个"转化器"(比如我们的充电线的接口),它能将现有的容器转化为新的,具有特定功能的东西,例如可以将vector,list…转化为stack

3.底层容器可以是任何容器,只需要满足empty,size,back,push_back,pop_back这些操作即可,如果没有我们自己写的容器,那么会使用标准的容器,例如vector,list…

.

2.stack的使用

我会为老铁们逐一演示stack的常用接口是如何使用的。

首先stack使用,需要包头文件

#include <stack>

栈的定义

stack<int> st;//栈里面数据类型是int型

栈的插入数据

stack<int> st;
//插入1 2 3 4
st.push(1);
st.push(2);
st.push(3);
st.push(4);

栈数据的遍历

这里需要注意一下,栈是没有迭代器的,那么我们该如何遍历栈里面的数据呢?

stack<int> st;
//插入1 2 3 4
st.push(1);
st.push(2);
st.push(3);
st.push(4);while (!st.empty())//判断栈里面的数据不为空
{int top = st.top();//取栈顶的数据st.pop();//删除该数据,让栈顶的数据进行迭代cout << top << endl;
}

代码的预期结果应该是4 3 2 1,那么我们来看看结果吧
在这里插入图片描述
结果正确!以上这些结果就是stack里面常用的接口了。

3.队列的定义

还是老规矩,我们先来看看c++官网文档对queue的介绍文档。
在这里插入图片描述

1.队列也是一种容器适配器,队列满足先进先出的性质,队列从队头出数据,从队尾入数据。

2.如果底层容器是我们自己设计的话,需要满足以下功能接口,empty,size,front,back,push_back,pop_front。

4.队列的使用

queue的使用和stack的使用一样,都是要包头文件

#include <queue>

队列的定义

queue<int> q;

队列的插入数据

queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);

队列中数据的遍历

queue也是没有迭代器的,所以queue的遍历操作和stack的遍历操作差不多

	queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);while (!q.empty()){int top = q.front();//取队头的数据cout << top << " ";q.pop();//让队头进行迭代}

代码的预期结果应该是1 2 3 4,那么我们来看看是不是这样
在这里插入图片描述

取队尾的元素

queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);cout << q.back() << endl;

在这里插入图片描述

求队列元素的个数

queue<int> q;
q.push(1);
q.push(2);
q.push(3);
q.push(4);cout << q.size() << endl;

在这里插入图片描述

5.stack的模拟实现

通过以上的知识,我们已经懂得了栈和队列的使用了,那么接下来,我们需要模拟栈和队列的实现了。

首先,我们需要定义一个命名空间,防止和库里面的冲突

namespace ljy
{}

再声明模板(不懂得可以看模板那一篇博客)

//T表示stack里面数据的类型,Container表示底层的容器
template<class T,class Container>

再定义类模板和声明底层容器的对象

template<class T,class Container>//T表示stack里面数据的类型,Container表示底层的容器
class stack
{
private:Container _con;//声明底层容器的对象
};

实现插入接口

public:void push(const T& x){_con.push_back(x);//调用底层容器的插入数据的接口}

实现删除栈顶数据的接口

void pop()
{_con.pop_back();//调用底层容器的删掉数据的接口
}

实现求栈的大小

size_t size()
{return _con.size();//调用底层容器的求数据个数的接口
}

实现栈判空

bool empty()
{return _con.empty();//调用底层容器的判断是否为空的接口
}

实现取栈顶的数据

T& top()
{return _con.back();//栈是后进先出
}

测试代码1

void test_stack1(){//定义一个栈,底层容器是数组stack<int, vector<int>> st1;st1.push(1);st1.push(2);st1.push(3);while (!st1.empty()){int top = st1.top();cout << top << " ";st1.pop();}cout << endl;}

执行代码看看有没有问题

#include "stack.h"
int main()
{ljy::test_stack1();return 0;
}

在这里插入图片描述

测试代码2

void test_stack2()
{//定义一个栈,底层容器是数组//stack<int, vector<int>> st1;//定义一个栈,底层容器是链表stack<int, list<int>> st1;st1.push(1);st1.push(2);st1.push(3);while (!st1.empty()){int top = st1.top();cout << top << " ";st1.pop();}cout << endl;
}
#include "stack.h"
int main()
{ljy::test_stack2();return 0;
}

在这里插入图片描述

结论:无论是数组还是链表都可以作为底层容器来模拟实现栈,所以可以推导出栈就是一个容器适配器!!!

6.queue模拟实现

queue的模拟实现和stack的模拟实现非常相似,只是队尾入,队头出而已。

#pragma once
#include <iostream>
#include <list>
#include <vector>
using namespace std;namespace ljy
{template<class T, class Container>//T表示queue里面数据的类型,Container表示底层的容器class queue{public:void push(const T& x)//队尾入{_con.push_back(x);//调用底层容器的插入数据的接口}void pop()//队头出{_con.pop_front();//调用底层容器的删掉数据的接口}size_t size(){return _con.size();//调用底层容器的求数据个数的接口}bool empty(){return _con.empty();//调用底层容器的判断是否为空的接口}T& front()//取队头数据{return _con.front();//队列是先进先出}T& back()//取队尾数据{return _con.back();//队列是先进先出}private:Container _con;};
}

测试代码

void test_queue()
{queue<int, vector<int>> q;q.push(1);q.push(2);q.push(3);q.push(4);while (!q.empty()){cout << q.front() << " ";q.pop();}cout << endl;
}

看一下运行结果有没有问题
在这里插入图片描述
直接报错了,我们看看报错内容,是头删出问题了,我们知道vector是不支持头删了,因为vector头删需要挪动数据,效率太低了,由于我们实现queue底层是使用vector容器,所有就直接报错了,我们把vector换成list看还有没有问题。

#pragma once
#include <iostream>
#include <list>
#include <vector>
using namespace std;namespace ljy
{template<class T, class Container>//T表示queue里面数据的类型,Container表示底层的容器class queue{public:void push(const T& x)//队尾入{_con.push_back(x);//调用底层容器的插入数据的接口}void pop()//队头出{_con.pop_front();//调用底层容器的删掉数据的接口}size_t size(){return _con.size();//调用底层容器的求数据个数的接口}bool empty(){return _con.empty();//调用底层容器的判断是否为空的接口}T& front()//取队头数据{return _con.front();//队列是先进先出}T& back()//取队尾数据{return _con.back();//队列是先进先出}private:Container _con;};void test_queue(){queue<int, list<int>> q;q.push(1);q.push(2);q.push(3);q.push(4);while (!q.empty()){cout << q.front() << " ";q.pop();}cout << endl;}
}

在这里插入图片描述
换成list就没问题了

7.deque容器

老规矩,我们先来看看有关deque容器的文档。
在这里插入图片描述
deque叫双端队列,但它不是队列,而是一种双开口,连续的空间的数据结构,那什么是双开口呢?双开口就是可以在头和在尾插入和删除数据,那么deque相比于vector效率就高很多了,deque相比于list空间的利用率较高。
在这里插入图片描述

deque的缺点

我们知道C++是一门极度注重效率的语言,deque虽然结合了list和vector的优点,但是deque并没有完全继承二者的优点,相比于二者各自的优点还是差点意思,所以deque代替不了vector和list
我们可以看看deque的随机访问和vector随机访问相差的时间
在这里插入图片描述

总结

以上就是关于STL中的stack和queue的全部内容,希望各位老铁看了这篇文章能有所收获。

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

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

相关文章

DNS缓存详解(DNS Cache Detailed Explanation)

DNS缓存详解 清空DNS缓存可以让网页访问更快捷。本文将从什么是DNS缓存、为什么清空DNS缓存、如何清空DNS缓存、清空DNS缓存存在的问题四个方面详细阐述DNS缓存清空的相关知识。 一、什么是DNS缓存 1、DNS缓存的定义&#xff1a; DNS缓存是域名系统服务在遇到DNS查询时自动…

OFDM系统仿真

1️⃣ OFDM的原理 1.1 介绍 OFDM是一种多载波调制技术&#xff0c;将输入数据分配到多个子载波上&#xff0c;每个子载波上可以独立使用 QAM、PSK 等传统调制技术进行调制。这些子载波之间互相正交&#xff0c;从而可以有效利用频谱并减少干扰。 1.2 OFDM的核心 多载波调制…

第11章:根据 ShuffleNet V2 迁移学习医学图像分类任务:甲状腺结节检测

目录 1. Shufflenet V2 2. 甲状腺结节检测 2.1 数据集 2.2 训练参数 2.3 训练结果 2.4 可视化网页推理 3. 下载 1. Shufflenet V2 shufflenet v2 论文中提出衡量轻量级网络的性能不能仅仅依靠FLOPs计算量&#xff0c;还应该多方面的考虑&#xff0c;例如MAC(memory acc…

网络编程套接字(中)

文章目录 &#x1f34f;简单的TCP网络程序服务端创建套接字服务端绑定服务端监听服务端获取连接服务端处理请求客户端创建套接字客户端连接服务器客户端发起请求服务器测试单执行流服务器的弊端 &#x1f350;多进程版的TCP网络程序捕捉SIGCHLD信号让孙子进程提供服务 &#x1…

happytime

happytime 一、查壳 无壳&#xff0c;64位 二、IDA分析 1.main 2.cry函数 总体&#xff1a;是魔改的XXTEA加密 在main中可以看到被加密且分段的flag在最后的循环中与V6进行比较&#xff0c;刚好和上面v6数组相同。 所以毫无疑问密文是v6. 而与flag一起进入加密函数的v5就…

DIFY源码解析

偶然发现Github上某位大佬开源的DIFY源码注释和解析&#xff0c;目前还处于陆续不断更新地更新过程中&#xff0c;为大佬的专业和开源贡献精神点赞。先收藏链接&#xff0c;后续慢慢学习。 相关链接如下&#xff1a; DIFY源码解析

Hot100之子串

560和为K的子数组 题目 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列 思路解析 ps&#xff1a;我们的presum【0】就是0&#xff0c;如果没有这个0的话我们的第一个元素就无法减去上…

网络工程师 (11)软件生命周期与开发模型

一、软件生命周期 前言 软件生命周期&#xff0c;也称为软件开发周期或软件开发生命周期&#xff0c;是指从软件项目的启动到软件不再被使用为止的整个期间。这个过程可以细分为多个阶段&#xff0c;每个阶段都有其特定的目标、任务和产出物。 1. 问题定义与需求分析 问题定义…

【Linux】使用管道实现一个简易版本的进程池

文章目录 使用管道实现一个简易版本的进程池流程图代码makefileTask.hppProcessPool.cc 程序流程&#xff1a; 使用管道实现一个简易版本的进程池 流程图 代码 makefile ProcessPool:ProcessPool.ccg -o $ $^ -g -stdc11 .PHONY:clean clean:rm -f ProcessPoolTask.hpp #pr…

MYSQL--一条SQL执行的流程,分析MYSQL的架构

文章目录 第一步建立连接第二部解析 SQL第三步执行 sql预处理优化阶段执行阶段索引下推 执行一条select 语句中间会发生什么&#xff1f; 这个是对 mysql 架构的深入理解。 select * from product where id 1;对于mysql的架构分层: mysql 架构分成了 Server 层和存储引擎层&a…

基于Spring Security 6的OAuth2 系列之七 - 授权服务器--自定义数据库客户端信息

之所以想写这一系列&#xff0c;是因为之前工作过程中使用Spring Security OAuth2搭建了网关和授权服务器&#xff0c;但当时基于spring-boot 2.3.x&#xff0c;其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0&#xff0c;结果一看Spring Security也升级…

深入剖析C语言字符串操作函数:my_strlen与my_strcpy

在C语言的编程世界里&#xff0c;字符串操作是日常开发中极为常见的任务。熟练掌握字符串操作函数&#xff0c;不仅能够提高代码的效率和可读性&#xff0c;还能为解决各种实际问题提供有力的支持。本文将深入剖析两个自定义的字符串操作函数&#xff1a; my_strlen 和 my_strc…

《苍穹外卖》项目学习记录-Day10来单提醒

type&#xff1a;用来标识消息的类型&#xff0c;比如说type1表示来单提醒&#xff0c;type2表示客户催单。 orderId&#xff1a;表示订单id&#xff0c;因为不管是来单提醒还是客户催单&#xff0c;这一次提醒都对应一个订单。是用户下了某个单或者催促某个订单&#xff0c;这…

数据结构与算法之栈: LeetCode 2042. 检查句子中的数字是否递增 (Ts版)

检查句子中的数字是否递增 https://leetcode.cn/problems/check-if-numbers-are-ascending-in-a-sentence/description/ 描述 句子是由若干 token 组成的一个列表&#xff0c;token 间用 单个 空格分隔&#xff0c;句子没有前导或尾随空格。每个 token 要么是一个由数字 0-9 …

fpga系列 HDL:XILINX Vivado Vitis 高层次综合(HLS) 实现 EBAZ板LED控制(上)

目录 创建工程创建源文件并编写C代码C仿真综合仿真导出RTL CG导出RTL错误处理&#xff1a; 创建工程 创建源文件并编写C代码 创建源文件(Souces下的hlsv.h和hlsv.cpp&#xff0c;Test Bench下的test_hlsv1.cpp)&#xff1a; hlsv1.h #ifndef HLSV1 #define HLSV1 #include &l…

JVM栈溢出线上环境排查

#查看当前Linux系统进程ID、线程ID、CPU占用率&#xff08;-eo后面跟想要展示的列&#xff09; ps H -eo pid,tid,%cpups H -eo pid,tid,%cpu |grep tid #使用java jstack 查看进程id下所有线程id的情况 jstack pid 案例2 通过jstack 排查死锁问题 #启动java代码 jstack 进…

91,【7】 攻防世界 web fileclude

进入靶场 <?php // 包含 flag.php 文件 include("flag.php");// 以高亮语法显示当前文件&#xff08;即包含这段代码的 PHP 文件&#xff09;的内容 // 方便查看当前代码结构和逻辑&#xff0c;常用于调试或给解题者提示代码信息 highlight_file(__FILE__);// 检…

Joplin 插件在Vscode中无法显示图片

1.问题 在vscode里面装好joplin插件之后&#xff0c;无法显示图片内容。 粘贴的图片可以再vscode中显示&#xff0c;无法再joplin客户端显示 2.解决方法 这种情况是因为和vscode自带的MD编辑器的预览模式有冲突&#xff0c;或者没用通过专用方式上传图片。 方法一&#xff…

FreeRTOS从入门到精通 第十七章(软件定时器)

参考教程&#xff1a;【正点原子】手把手教你学FreeRTOS实时系统_哔哩哔哩_bilibili 一、软件定时器简介 1、定时器的概念与种类 &#xff08;1&#xff09;定时器的概念&#xff1a;从指定的时刻开始&#xff0c;经过一个指定时间&#xff0c;然后触发一个超时事件&#xf…

2025年美赛B题-结合Logistic阻滞增长模型和SIR传染病模型研究旅游可持续性-成品论文

模型设计思路与创新点&#xff1a; 建模的时候应该先确定我们需要建立什么类的模型&#xff1f;优化类还是统计类&#xff1f;这个题需要大量的数据分析&#xff0c;因此我们可以建立一个统计学模型。 统计学建模思路&#xff1a;观察规律&#xff0c;建立模型&#xff0c;参…