【C++】_stack和_queue容器适配器、_deque

当别人都在关注你飞的有多高的时候,只有父母在关心你飞的累不累。💓💓💓

目录

  ✨说在前面

🍋知识点一:stack

•🌰1.stack介绍

•🌰2.stack的基本操作

🍋知识点二:queue

•🌰2.queue介绍

•🌰2.queue的基本操作

🍋知识点三:priority_queue

•🌰1.priority_queue介绍

•🌰2.priority_queue的基本使用

•🌰3.仿函数

🔥仿函数控制序列单调性

🔥仿函数在优先级队列中的应用

🍋知识点四:容器适配器

•🌰1.什么是适配器

•🌰2.stack和queue的底层结构

•🌰3.deque介绍

🔥deque的实现原理

🔥deque的缺陷

🔥选择deque的原因

 • ✨SumUp结语


  ✨说在前面

亲爱的读者们大家好!💖💖💖,我们又见面了,上一篇文章我给大家介绍了一下list的定义、常用接口以及模拟实现。如果大家没有掌握好相关的知识,上一篇篇文章讲解地很详细,可以再回去看看,复习一下,再进入今天的内容。

我们今天简单给大家讲解一下STL中的两大适配器——stack和queue。stack和queue分别对应C语言中的栈和队列,如果大家准备好了,那就接着往下看吧~

   👇👇👇
💘💘💘知识连线时刻(直接点击即可)

【C++】_string类字符串万字详细解析

【C++】_vector定义、_vector常用方法解析

【C++】_list常用方法解析及模拟实现

  🎉🎉🎉复习回顾🎉🎉🎉

         

 博主主页传送门:愿天垂怜的博客

 ​​​​​​

 

🍋知识点一:stack

•🌰1.stack介绍

stack是一个容器适配器,它提供了一种后进先出(LIFO, Last In First Out)的数据结构。stack只允许在容器的顶部进行元素的添加(push)和移除(pop)操作,以及访问顶部元素(top)的功能,但不提供遍历容器内部元素的功能

我们来查看一下文档中对stack的介绍:

注意:stack不属于容器,而是一种容器适配器。它看起来像是容器,但实际上它们是通过封装其他容器来工作的。

•🌰2.stack的基本操作

stack的使用接口如下:

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

它的接口非常简单,实现部分可以参考C语言的写法:C语言实现栈和队列

如果大家觉得不好理解,可以看我之前写的栈和队列的博客:【数据结构】栈和队列超详细讲解

接口文档如下:

stack::stack - C++ Reference (cplusplus.com)

stack::empty - C++ Reference (cplusplus.com)

stack::size - C++ Reference (cplusplus.com)

stack::top - C++ Reference (cplusplus.com)

stack::push - C++ Reference (cplusplus.com)

stack::emplace - C++ Reference (cplusplus.com)

stack::pop - C++ Reference (cplusplus.com)

stack::swap - C++ Reference (cplusplus.com)

 ​​​​​​

🍋知识点二:queue

•🌰2.queue介绍

queue是一种先进先出(FIFO, First In First Out)的数据结构。它允许在队尾添加元素(enqueue/push),在队首移除元素(dequeue/pop),以及查看队首元素(front)的值。与stack类似,queue也不提供遍历功能

我们来查看一下文档中对queue的介绍:

 注意:queue不属于容器,而是一种容器适配器。它看起来像是容器,但实际上它们是通过封装其他容器来工作的。

 

•🌰2.queue的基本操作

stack的使用接口如下:

函数说明接口说明
queue()构造空的队列
empty()检测队列是否为空,是返回true,否则返回false
size()返回队列中元素的个数
front()返回队头元素的引用
back()返回队尾元素的引用

push()

在队尾将元素val入队列
pop()

将队头元素出队列

它的接口非常简单,实现部分可以参考C语言的写法:C语言实现栈和队列

如果大家觉得不好理解,可以看我之前写的栈和队列的博客:【数据结构】栈和队列超详细讲解

接口文档如下:

queue::queue - C++ Reference (cplusplus.com)

queue::empty - C++ Reference (cplusplus.com)

queue::size - C++ Reference (cplusplus.com)

queue::front - C++ Reference (cplusplus.com)

queue::back - C++ Reference (cplusplus.com)

queue::push - C++ Reference (cplusplus.com)

queue::emplace - C++ Reference (cplusplus.com)

queue::pop - C++ Reference (cplusplus.com)

queue::swap - C++ Reference (cplusplus.com)

 ​​​​​​

🍋知识点三:priority_queue

•🌰1.priority_queue介绍

学习完了队列,我们再来了解一下优先级队列:

C++中的优先级队列(Priority Queue)是一种特殊的队列,它的元素被赋予优先级,元素的出队顺序基于它们的优先级,而不是它们被加入队列的顺序。默认情况下,priority_queue使用最大堆(Max Heap)来实现,所以队列中最大的元素总是位于队列的顶部,因此这个元素会首先被移除(即出队)。

 

•🌰2.priority_queue的基本使用

优先级队列默认使用vector作为其底层存储数据的容器在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆

相同地,priority_queue也有如下接口:

函数声明接口说明
priority_queue()/priority_queue(first, last)
构造一个空的优先级队列
empty( )检测优先级队列是否为空,是返回true,否则返回false
top( )返回优先级队列中最大(最小元素),即堆顶元
push(x)在优先级队列中插入元素x
pop()
删除优先级队列中最大 ( 最小 ) 元素,即堆顶元

接口文档如下:

priority_queue::priority_queue - C++ Reference (cplusplus.com)

priority_queue::empty - C++ Reference (cplusplus.com)

priority_queue::size - C++ Reference (cplusplus.com)

priority_queue::top - C++ Reference (cplusplus.com)

priority_queue::push - C++ Reference (cplusplus.com)

priority_queue::emplace - C++ Reference (cplusplus.com)

priority_queue::pop - C++ Reference (cplusplus.com)

priority_queue::swap - C++ Reference (cplusplus.com)

 

•🌰3.仿函数

仿函数(Functors)是那些重载了()操作符的对象,它们的行为类似于函数。通过使用仿函数,你可以将函数的行为封装在对象内部,这样做的好处包括能够传递额外的状态信息、支持泛型编程(例如,与标准库算法一起使用时),以及更好的封装性。

🔥仿函数控制序列单调性

下面是一个仿函数示例,用于控制冒泡排序将原先序列按递增还是递减顺序排列:

//递增
template<class T>
class Less
{
public:bool operator()(const T& x, const T& y){return x < y;}
};
//递减
template<class T>
class Greater
{
public:bool operator()(const T& x, const T& y){return x > y;}
};
//冒泡排序
template<class Compare>
void BubbleSort(int* arr, int length, Compare com)
{assert(arr);int flag = 1;while (flag && length--){flag = 0;for (int i = 0; i < length; i++){//if (arr[i] > arr[i + 1])if (com(arr[i], arr[i + 1])){swap(arr[i], arr[i + 1]);flag = 1;}}}
}
//打印数组元素
void printArr(int* arr, int length)
{for (size_t i = 0; i < length; i++){cout << arr[i] << " ";}cout << endl;
}int main()
{Less<int> LessFunc;Greater<int> GreaterFunc;int arr[] = { 5,23,789,12,8,1,86,12,7 };//升序BubbleSort(arr, 9, GreaterFunc);printArr(arr, 9);//降序BubbleSort(arr, 9, LessFunc);printArr(arr, 9);return 0;

在这个例子中,Less类和Greater类是仿函数,它重载了()操作符以比较两个整数。我们创建了Less或Greater的实例并将其作为第三个参数传递给BubbleSort函数,以指定排序的准则

结果如下:

1 5 7 8 12 12 23 86 789
789 86 23 12 12 8 7 5 1

 

🔥仿函数在优先级队列中的应用

利用仿函数,我们可以控制优先级队列的底层是大堆还是小堆,进而控制优先级队列的优先级。我们默认优先级队列的底层是大堆

它的实现用到了仿函数,可以参考我这里的实现:优先级队列模拟实现

优先级队列举例:

#include <iostream>
using namespace std;
#include <queue>int main()
{priority_queue<int> pq;pq.push(3);pq.push(7);pq.push(1);pq.push(9);pq.push(10);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}return 0;
}

结果如下:

10 9 7 3 1

 ​​​​​​

🍋知识点四:容器适配器

•🌰1.什么是适配器

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

•🌰2.stackqueue的底层结构

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

我们来看看stack的模拟实现:

namespace stl_stack
{//Container适配转换出stacktemplate<class T, class Container>class stack{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_back();}const T& top(){return _con.back();}size_t size() const{return _con.size();}bool empty(){return _con.empty();}private:Container _con;};
}

再来看看stack的模拟实现:

很显然我们发现,这里容器的缺省值给的是deque<T>,这是个什么东西呢?继续往下看。

•🌰3.deque介绍

🔥deque的实现原理

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高

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

双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器设计就比较复杂,如下图所示:

 

🔥deque的缺陷

与vector相比,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是比vector高的。

与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

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

我们可以用下面的代码来测试vector和deque的[]利率:

//deque与vector[]的效率对比
void test_op1()
{srand(time(0));const int N = 1000000;deque<int> dq;vector<int> v;for (int i = 0; i < N; ++i){auto e = rand() + i;dq.push_back(e);v.push_back(e);}int begin1 = clock();sort(dq.begin(), dq.end());int end1 = clock();int begin2 = clock();sort(v.begin(), v.end());int end2 = clock();printf("deque:%d\n", end1 - begin1);printf("vector:%d\n", end2 - begin2);
}void test_op2()
{srand(time(0));const int N = 1000000;deque<int> dq1;deque<int> dq2;for (int i = 0; i < N; ++i){auto e = rand() + i;dq1.push_back(e);dq2.push_back(e);}int begin1 = clock();sort(dq1.begin(), dq1.end());int end1 = clock();int begin2 = clock();//拷贝到vectorvector<int> v(dq2.begin(), dq2.end());sort(v.begin(), v.end());dq2.assign(v.begin(), v.end());int end2 = clock();printf("deque sort:%d\n", end1 - begin1);printf("deque copy vector sort, copy back deque:%d\n", end2 - begin2);
}int main()
{test_op1();test_op2();return 0;
}

realse且x86结果如下:

deque:117
vector:66
deque sort:104
deque copy vector sort, copy back deque:59

 基本上相差两倍左右。

 

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

结合了deque的优点,而完美的避开了其缺陷。

 ​

 • ✨SumUp结语

到这里本篇文章的内容就结束了,本节介绍了C++中_stack_queue的相关知识。这里的内容虽然很熟悉了,而且也很简单。但是也希望大家能够认真学习,打好基础,迎接接下来的挑战,期待大家继续捧场~💖💖💖

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

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

相关文章

【电路笔记】-反相运算放大器

反相运算放大器 文章目录 反相运算放大器1、概述2、理想反相运算放大器3、实际反相运算放大器3.1 闭环增益3.2 输入阻抗3.3 输出阻抗4、反相运算放大器示例5、总结1、概述 上一篇关于同相运算放大器的文章中已介绍了该运算放大器配置的所有细节,该配置在同相引脚 (+) 上获取输…

LSS如何创建视锥

1 完整代码 def create_frustum(self):# 128 352, 22 8in_H

LRELHLNNN;亲水性抗肝纤维化多肽作为基础肽;I型胶原蛋白靶向肽;九肽LRELHLNNN

【LRELHLNNN 简介】 LRELHLNNN是一种多肽&#xff0c;它能够选择性地结合到I型胶原蛋白&#xff0c;具有亲和力为170 nM。LRELHLNNN是由9个氨基酸组成&#xff0c;其氨基酸序列为H-Leu-Arg-Glu-Leu-His-Leu-Asn-Asn-Asn-OH。LRELHLNNN因其与I型胶原蛋白的高亲和力而在生物医学领…

MDC日志追踪(一)介绍

一、背景 在排查问题时&#xff0c;如果只根据关键字搜索&#xff0c;可能不精准&#xff0c;比如根据userId搜索&#xff0c;但是这个userId访问的记录也很多&#xff0c;很难定位出问题的是哪一次的&#xff1b;比如根据其他关键字搜索如orderId&#xff0c;可能很多用户都访…

wifi贴码推广能赚钱吗?wifi贴码怎么跟商家沟通?

大家好&#xff0c;我是鲸天科技千千&#xff0c;大家都知道我是做开发的&#xff0c;平时会给大家分享一些互联网相关的创业项目和网络技巧&#xff0c;感兴趣的可以给我点个关注。 最近WiFi这个项目很多朋友来问我&#xff0c;我是前两年就接触过这个&#xff0c;所以比较了…

“孪舟”引擎V5.0:更有颜、更真实、更智能、更灵活、更强大

在9月6日智汇云舟2024视频孪生产品发布会上&#xff0c;我们向线上线下嘉宾展示了基于视频孪生技术的众多产品&#xff0c;以及前沿技术。我们的目标是依托自研3DGIS引擎&#xff0c;将视频、AI、IoT等多种技术深度融合&#xff0c;升级数字孪生为视频孪生&#xff0c;实时实景…

《Putty 的下载和安装步骤》

Putty 是一款免费开源的 SSH 和 Telnet 客户端,它主要用于远程登录和管理其他计算机或服务器。 1.Putty 的一些主要特点和优势: 1. 简单易用:它具有直观的用户界面,操作相对简单,即使对于不太熟悉技术的用户也能轻松上手。 2. 支持多种协议:除了 SSH(Secure Shell)…

「漏洞复现」紫光电子档案管理系统 selectFileRemote SQL注入漏洞

0x01 免责声明 请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;作者不为此承担任何责任。工具来自网络&#xff0c;安全性自测&#xff0c;如有侵权请联系删…

亚马逊跨境新手小白如何选品?实操带练教程

选产品和找供应&#xff0c;是每个跨境人不可避免的&#xff0c;但是盲目的选品&#xff0c;无疑是大海捞针。最近我发现一个宝藏工具-店雷达&#xff0c;它可以帮助你选品的同时&#xff0c;同时还能为你筛选供应商。 我就分享一下我用店雷达的选品方法和思路&#xff0c;大家…

【TPAMI 2024】竟能如此丝滑的过渡,从2D生成对抗网络数据逐步学习3D重建网络!

题目&#xff1a;Progressive Learning of 3D Reconstruction Network From 2D GAN Data 从2D生成对抗网络数据逐步学习3D重建网络 作者&#xff1a;Aysegul Dundar; Jun Gao; Andrew Tao; Bryan Catanzaro ** 关注公众号&#xff1a;AI前沿速递&#xff0c;获取更多优质资源…

NV080D语音芯片赋能电子秤一体机人机交互新革新

随着科技的飞速发展&#xff0c;零售业正经历着前所未有的变革。九芯作为行业的领跑者&#xff0c;推出了革命性的NV080D语音芯片&#xff0c;为超市、水果店、熟食店、麻辣烫店等零售业态带来了智能化的全新体验。 NV080D语音芯片在电子秤上的应用&#xff0c;主要是为了提高检…

[ComfyUI]Flux:写真新篇章!字节PuLID率先开启一致性风格迁移,无损画手和优质画面保持

前言 Flux&#xff1a;PuLID率先开启F1写真新篇章 所有的AI设计工具&#xff0c;模型和插件&#xff0c;都已经整理好了&#xff0c;&#x1f447;获取~ Flux PuLID简介 在Flux出来后短时间内&#xff0c;社区生态反响和发展足够的迅猛快速。至今为止&#xff0c;社区LORA模…

c++面试-语法糖(一)

c面试-语法糖(一) 1、const关键字的作用&#xff1f;(变量&#xff0c;参数&#xff0c;返回值) 定义常量值&#xff1a;const 可以用于定义常量变量&#xff0c;其值在初始化后不能被修改。 const int MAX_SIZE 100;修饰指针&#xff1a;const 可以修饰指针&#xff0c;表示…

69、Python番外篇:从编程范式看如何学习一门编程语言的精髓

引言 在之前的文章中&#xff0c;我们曾聊过如何学习一门编程语言&#xff0c;当时是从程序的构成的角度来分析、展开的&#xff0c;主要提及了数据的表达 数据的处理&#xff0c;也就是数据结构 算法的内容。这个角度对应到所有编程语言&#xff0c;基本都是适用的。但是&a…

负载均衡:从理论到实践 ---day04

负载均衡 负载均衡1.什么是负载均衡2.负载均衡的分类硬件负载均衡软件负载均衡选择 3.引入负载均衡的好处 第一个Ribbon实例步骤1&#xff1a;步骤2&#xff1a;步骤3&#xff1a;步骤4&#xff1a; 问题1. 负载均衡的主要目标是什么&#xff1f;2. 负载均衡器的作用是什么&…

网络安全 DVWA通关指南 DVWA SQL Injection (Blind SQL盲注)

DVWA SQL Injection (Blind) 文章目录 DVWA SQL Injection (Blind)Low布尔盲注时间盲注sqlmap MediumHighImpossible 参考文献 WEB 安全靶场通关指南 Low 0、分析网页源代码 <?phpif( isset( $_GET[ Submit ] ) ) {// Get input$id $_GET[ id ];// Check database$geti…

鸿蒙HarmonyOS开发:一次开发,多端部署(界面级)天气应用案例

文章目录 一、布局简介二、典型布局场景三、侧边栏 SideBarContainer1、子组件2、属性3、事件 四、案例 天气应用1、UX设计2、实现分析3、主页整体实现4、具体代码 五、运行效果 一、布局简介 布局可以分为自适应布局和响应式布局&#xff0c;二者的介绍如下表所示。 名称简介…

DSLogic 逻辑分析仪的使用-I2C协议

一、I2C IIC-BUS&#xff08;Inter-IntegratedCircuit Bus&#xff09;最早是由PHilip半导体&#xff08;现在被NXP收购&#xff09;于1982年开发。 主要是用来方便微控制器与外围器件的数据传输。 它是一种半双工&#xff0c;由SDA&#xff08;数据&#xff09;和SCL&#xf…

MicroPython 片上psrom的支持,并将多个bin合成为一个bin

前两天在github上下载的MicroPython 版本1.20.0&#xff0c;怎么配置都无法开启片上psrom的支持&#xff0c;折腾了一周&#xff0c;都自我怀疑了&#xff0c;最后更新版本为1.23.0一编译直接就过了。。。下面记录下过的&#xff0c;过程&#xff0c;这边使用的是四线SPI的片上…

我平时是怎么找客户的?今天我的实战技巧,分享给大家

我常用的几个方法 1、利用WhatsApp&#xff0c;找客户的号码&#xff0c;去进行营销 学会这个方法&#xff0c;WhatsApp账号都能被你找到http://mp.weixin.qq.com/s?__bizMzg2MTcxNzAwMg&mid2247498845&idx1&sn039a87d60094cf6c166e2cf5e1f94a69&chksmce106…