C++修炼:stack和queue

news2025/5/14 0:31:01

        Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路!

我的博客:<但凡.

我的专栏:《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C++修炼之路》

欢迎点赞,关注!

目录

1、stack和queue的使用

1.1、stack

1.2、queue

2、stack和queue的模拟实现

2.1、容器适配器

2.2、模拟实现

3、list,vector,deque的对比

3.1、list和vector对比

3.2、缓存命中率

3.3、deque


 

1、stack和queue的使用

1.1、stack

        栈这个数据结构相信大家都不陌生了,在这我就不过多介绍了,我们直接使用stl中的栈进行一些基础操作。

#include<iostream>
#include<stack>
using namespace std;
int main()
{
	stack<int> st;
	st.push(1);//插入操作
	st.push(2);
	st.push(3);
	st.push(4);
	st.push(5);
	st.push(6);
	st.push(7);

	while (st.size())
	{
		cout << st.top() <<" ";//取栈顶操作
		st.pop();
	}
}

        stack的接口很少,并且stack不支持迭代器。以上操作输出结果为7 6 5 4 3 2 1。

1.2、queue

        队列这个结构我们也很熟悉了,这里的queue和stack一样也不支持迭代器访问,并且接口也很少。我们拿和上面一样的方法来使用一下。

#include<iostream>
#include<queue>
using namespace std;
int main()
{
	queue<int> q;
	q.push(1);//插入操作
	q.push(2);
	q.push(3);
	q.push(4);
	q.push(5);
	q.push(6);
	q.push(7);

	while (q.size())
	{
		cout << q.front() << " ";//输出队头
		q.pop();
	}
	cout << endl;

	q.push(1);
	cout << q.back() << endl;//支持输出队尾
}

输出结果:

2、stack和queue的模拟实现

2.1、容器适配器

        现在我们进入第二个阶段模拟实现。我们前两篇list和vector都用了很大的篇幅去模拟实现,但是stack和queue就很简单了。因为我们可以用到一个叫 容器适配器 的东西来帮助我们。

​        

        我们注意到STL底层在实现这两个数据结构的时候用了一个叫Container(容器适配器)的东西。 

        在 C++ 标准模板库(STL)中,容器适配器(Container Adaptor) 是一种特殊的容器,它们基于现有的 STL 容器(如 std::dequestd::list 或 std::vector)进行封装,所以本质上是一种复用,就像我们之前在模拟实现string里面部分接口是复用了memcpy,memset这种库里已经写好的函数。只不过这回我们复用的不是函数了而是一个容器,一个写好的数据结构。

        使用容器适配器的结构不能通过迭代器访问,因为这样可能会破坏这个容器的使用规则,比如栈要求后进先出,而queue要求先进先出。虽然不能用迭代器但是我们可以更换底层容器(deque,vector,list等)。

        现在我们来模拟实现以下stack和queue。

2.2、模拟实现

        模拟实现stack:

template<class T,class con=deque<T>>
class stack
{
public:
	stack()
	{}

	void push(const T& x)
	{
		_c.push_back(x);
	}
	void pop()
	{
		_c.pop_back();
	}
	T& top()
	{
		return _c.back();
	}
	const T& top() const
	{
		return _c.back();
	}
	size_t size() const
	{
		return _c.size();
	}
	bool empty() const
	{
		return _c.empty();
	}
private:
	con  _c;//默认调用deque的构造
};

        模拟实现queue:

template<class T,class con=deque<T>>
class queue
{
public:
	queue()
	{}
	void push(const T& x) {
		_c.push_back(x);
	}
	void pop() {
		_c.pop_front();
	}

	T& back() { return _c.back(); }
	const T& back() const  { return _c.back(); }
	T& front() { return _c.front(); }
	const T& front() const  { return _c.front(); }

	size_t size() {
		return _c.size();
	}
	bool empty() const
	{
		return _c.empty;
	}
private:
	con _c;
};

        我们可以用刚开始写的代码测试一下他们的逻辑发现没有问题,符合栈和队列的使用规范。 

        我们同样可以把适配器换成vector和list,其他不用改变。在这里我就不再演示了。

        那现在就有一个问题,list,deque,vector这三种容器作为适配器有什么区别呢?到底哪个更好呢?

3、list,vector,deque的对比

3.1、list和vector对比

        我们先来看list和vector,这两个容器的特点可以说是两个极端或者说是两个对立。

        list的优点是插入,删除效率高,任意位置插入删除时间复杂度都是O(1)级别。

并且空间利用率高,节点都是按需申请,按需释放的。

        而vector的与list相比在这两方面都是劣势,缺点。vector头插和头删需要挪动数据,效率低下。并且存在扩容浪费空间的问题。比如说我们申请二十个空间,但实际上我们只插入一个元素。

        那vector有什么优点呢?首先它支持迭代器随机访问,而list是不支持迭代器随机访问的。当然了这一点也不是那么重要因为做适配器根本就不能用迭代器访问。

        第二点非常重要也是大家以前可能从来没听说过的,vector的cpu高速缓冲命中率高,而list的cpu高速缓存命中率低。

        什么是cpu高速缓存命中率呢?我们展开解释一下。

3.2、缓存命中率

        我们先来补充一点作为程序员,应该知道的有关cpu的“常识”。

        我们的cpu现在基本都有三级缓存(L3,L2,L1),当然较老的cpu只有两级缓存(L2,L1),他们的访问速度L3>L2>L1,在这之后还有内存,硬盘。当然了硬盘的访问速度就很慢了。我们的数据从内存,先到L3,再到L2,再到L1,然后到寄存器中进行cpu计算。

        数据的距离cpu核心越来越近、因为L1,L2分布在cpu的每一个核中,而L3是所有cpu核共有的内存。

注:上图展示的是一个4核CPU的缓存结构示例,而现代主流CPU通常配备6-16个物理核心,服务器级CPU甚至可达128核。随着核心数量增加,实际缓存架构会存在些许差异。

        那我们数据是通过什么一层一层的往上走的呢?首先明确一点他不是一个字节一个字节加载向上走的,而是一块一块的向上走的。什么意思?我们打个比方。我们在写文章的时候,如果想引用什么名人名言可以去百度上搜索,比如我搜索出了一段鲁迅说过的话,想把他复制到我的文章中,我肯定不是一个字一个字的复制的吧?那样也太累了。我们肯定是把一段话都复制下来然后放到文章中。

        cpu也是,如果傻傻的一个字节一个字节的挪动数据那也太慢了,他是一块一块的挪动,那么这一块数据单位就叫一个“Cache Line”。

        那为什么vector缓存命中率高呢?比方说我们就挪动64字节(目前主流cpu的Cache Line是64字节),恰巧我们64个字节是存储的连续的16个int类型数据,那好了我一次性都加载走了。

        但如果是list呢?他的内存分布是不连续的,是这一块内存一个数据,那一块内存一个数据,倘若我对于某一块内存扫描64字节的话,可能只能挪走一个数据,甚至一个也挪不到。那命中率就低了。进而效率也就低了。

        介绍完vector和list以及缓存命中率,我们再来看一下deque。

3.3、deque

        deque(双端队列)是一种支持高效头尾插入/删除的序列容器,它结合了vector和list的优缺点,既支持随机访问,又能高效的插入和删除。

        deque可以说是把两者融合了一下,但是由于他的底层逻辑设计起来比较复杂,他的头插尾插效率高,但是高不过list,他的cpu缓存命中率比list优秀,但是也优秀不过vector。我们在这里不模拟实现他,但是我们说一下他的底层是什么样子的。        

        deque通常由多个固定大小的连续内存块(分块数组)通过中央控制器(如指针数组)链接而成,具体结构如下:

        (1)分块储存

        每个内存块存储若干元素,独立分配,插入新元素无需整体挪动,只需要分配新的内存块

        (2)中央映射表

        通过一个存储着每块内存地址的数组来快速找到这块内存。

        STL中对stack和queue默认选择deque作为其底层容器,主要是因为:

        1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。

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

        好了,今天的内容就分享到这,我们下期再见!

 

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

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

相关文章

【计算机视觉】优化MVSNet可微分代价体以提高深度估计精度的关键技术

优化MVSNet可微分代价体以提高深度估计精度的关键技术 1. 代价体基础理论与分析1.1 标准代价体构建1.2 关键问题诊断 2. 特征表示优化2.1 多尺度特征融合2.2 注意力增强匹配 3. 代价体构建优化3.1 自适应深度假设采样3.2 可微分聚合操作改进 4. 正则化与优化策略4.1 多尺度代价…

软考错题集

一个有向图具有拓扑排序序列&#xff0c;则该图的邻接矩阵必定为&#xff08;&#xff09;矩阵。 A.三角 B.一般 C.对称 D.稀疏矩阵的下三角或上三角部分包含非零元素&#xff0c;而其余部分为零。一般矩阵这个术语太过宽泛&#xff0c;不具体指向任何特定性 质的矩阵。对称矩阵…

T2I-R1:通过语义级与图像 token 级协同链式思维强化图像生成

文章目录 速览摘要1 引言2 相关工作统一生成与理解的 LMM(Unified Generation and Understanding LMM.)用于大型推理模型的强化学习(Reinforcement Learning for Large Reasoning Models.)3 方法3.1 预备知识3.2 语义级与令牌级 CoT语义级 CoT(Semantic-level CoT)令牌级…

Dockers部署oscarfonts/geoserver镜像的Geoserver

Dockers部署oscarfonts/geoserver镜像的Geoserver 说实话&#xff0c;最后发现要选择合适的Geoserver镜像才是关键&#xff0c;所以所以所以…&#x1f437; 推荐oscarfonts/geoserver的镜像&#xff01; 一开始用kartoza/geoserver镜像一直提示内存不足&#xff0c;不过还好…

扩增子分析|微生物生态网络稳定性评估之鲁棒性(Robustness)和易损性(Vulnerability)在R中实现

一、引言 周集中老师团队于2021年在Nature climate change发表的文章&#xff0c;阐述了网络稳定性评估的原理算法&#xff0c;并提供了完整的代码。自此对微生物生态网络的评估具有更全面的指标&#xff0c;自此网络稳定性的评估广受大家欢迎。本系列将介绍网络稳定性之鲁棒性…

【含文档+PPT+源码】基于微信小程序的社区便民防诈宣传系统设计与实现

项目介绍 本课程演示的是一款基于微信小程序的社区便民防诈宣传系统设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套…

【MySQL】存储引擎 - ARCHIVE、BLACKHOLE、MERGE详解

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…

代码随想录第41天:图论2(岛屿系列)

一、岛屿数量&#xff08;Kamacoder 99&#xff09; 深度优先搜索&#xff1a; # 定义四个方向&#xff1a;右、下、左、上&#xff0c;用于 DFS 中四向遍历 direction [[0, 1], [1, 0], [0, -1], [-1, 0]]def dfs(grid, visited, x, y):"""对一块陆地进行深度…

VUE CLI - 使用VUE脚手架创建前端项目工程

前言 前端从这里开始&#xff0c;本文将介绍如何使用VUE脚手架创建前端工程项目 1.预准备&#xff08;编辑器和管理器&#xff09; 编辑器&#xff1a;推荐使用Vscode&#xff0c;WebStorm&#xff0c;或者Hbuilder&#xff08;适合刚开始练手使用&#xff09;&#xff0c;个…

Java EE初阶——初识多线程

1. 认识线程 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程中的实际运作单位。 基本概念&#xff1a;一个进程可以包含多个线程&#xff0c;这些线程共享进程的资源&#xff0c;如内存空间、文件描述符等&#xff0c;但每个线程都有自己独…

如何删除网上下载的资源后面的文字

这是我在爱给网上下载的音效资源&#xff0c;但是发现资源后面跟了一大段无关紧要的文本&#xff0c;但是修改资源名称后还是有。解决办法是打开属性然后删掉资源的标签即可。

FPGA图像处理(5)------ 图片水平镜像

利用bram形成双缓冲&#xff0c;如下图配置所示&#xff1a; wr_flag 表明 buffer0写 还是 buffer1写 rd_flag 表明 buffer0读 还是 buffer1读 通过写入逻辑控制(结合wr_finish) 写哪个buffer &#xff1b;写地址 进而控制ip的写使能 通过状态缓存来跳转buffer的…

day21python打卡

知识点回顾&#xff1a; LDA线性判别PCA主成分分析t-sne降维 还有一些其他的降维方式&#xff0c;也就是最重要的词向量的加工&#xff0c;我们未来再说 作业&#xff1a; 自由作业&#xff1a;探索下什么时候用到降维&#xff1f;降维的主要应用&#xff1f;或者让ai给你出题&…

ERP学习(一): 用友u8安装

安装&#xff1a; https://www.bilibili.com/video/BV1Pp4y187ot/?spm_id_from333.337.search-card.all.click&vd_sourced514093d85ee628d1f12310b13b1e59b 我个人用vmware16&#xff0c;这位up已经把用友软件和环境&#xff08;sqlserver2008&#xff09; 都封城vmx文件了…

01 | 大模型微调 | 从0学习到实战微调 | AI发展与模型技术介绍

一、导读 作为非AI专业技术开发者&#xff08;我是小小爬虫开发工程师&#x1f60b;&#xff09; 本系列文章将围绕《大模型微调》进行学习&#xff08;也是我个人学习的笔记&#xff0c;所以会持续更新&#xff09;&#xff0c;最后以上手实操模型微调的目的。 (本文如若有…

海康相机无损压缩

设置无损压缩得到更高的带宽和帧率&#xff01;

从机器人到调度平台:超低延迟RTMP|RTSP播放器系统级部署之道

✅ 一、模块定位&#xff1a;跨平台、超低延迟、系统级稳定的音视频直播播放器内核 在无人机、机器人、远程操控手柄等场景中&#xff0c;低延迟的 RTSP/RTMP 播放器并不是“可有可无的体验优化”&#xff0c;而是系统能否闭环、操控是否安全的关键组成。 Windows和安卓播放RT…

研发效率破局之道阅读总结(5)管理文化

研发效率破局之道阅读总结(5)管理文化 Author: Once Day Date: 2025年5月10日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 程序的艺术_Once-Day…

单因子实验 方差分析

本文是实验设计与分析&#xff08;第6版&#xff0c;Montgomery著傅珏生译)第3章单因子实验 方差分析python解决方案。本文尽量避免重复书中的理论&#xff0c;着于提供python解决方案&#xff0c;并与原书的运算结果进行对比。您可以从 下载实验设计与分析&#xff08;第6版&a…

Bitacora:基因组组件中基因家族识别和注释的综合工具

软件教程 | Bitacora&#xff1a;基因组组件中基因家族识别和注释的综合工具 https://zhangzl96.github.io/tags#生物信息工具) &#x1f4c5; 官方地址&#xff1a;https://github.com/molevol-ub/bitacora &#x1f52c; 教程版本&#xff1a;BITACORA 1.4 &#x1f4cb; …