【C++】stack 和 queue 以及 容器适配器

文章目录

  • 一、stack
    • 1.1 stack的使用
    • 1.2 stack的模拟实现
  • 二、queue
    • 2.1 queue的使用
    • 2.2 queue的模拟实现
  • 三、优先级队列
    • 1.优先级队列的介绍
    • 2. priority_queue的使用的使用
    • 3.模拟实现优先级队列
  • 四、 容器适配器
    • 1.STL标准库中stack和queue的底层结构
    • 2.deque(双端对列)了解
      • 2.1deque的概念
      • 2.2deque的缺陷
      • 2.3为什么选择deque作为stack和queue的底层默认容器
  • 五、STL标准库中对于stack和queue的模拟实现
    • stack的模拟实现
    • queue的模拟实现

一、stack

栈的特点是先进后出,stack不提供迭代器。

1.1 stack的使用

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

1.2 stack的模拟实现

从栈的接口中可以看出,栈实际是一种特殊的vector,因此使用vector完全可以模拟实现stack。

#include<vector>
namespace fx
{
template<class 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:std::vector<T> _c;
};
}

二、queue

队列的特点是先进先出,queue不提供迭代器

2.1 queue的使用

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

2.2 queue的模拟实现

queue的底层可以是list等支持尾插头删的线性容器,但并不支持vector,因为数组头插头删效率不行。

#include <list>
namespace fx
{
template<class 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()const {return _c.size();}bool empty()const {return _c.empty();}
private:std::list<T> _c;
};
}

三、优先级队列

1.优先级队列的介绍

在有了前面容器使用的基础之下,我们对于优先级队列priority_queue的使用成本不是很大,值得注意的是头文件为 < queue>

普通的队列是先进先出,优先级队列默认是优先级高的先出
在这里插入图片描述
Container: 优先级队列默认使用vector作为其底层存储数据的容器,支持[]的使用,支持随机访问,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。

Compare:注意:默认情况下priority_queue是大堆,仿函数为less。

2. priority_queue的使用的使用

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

3.模拟实现优先级队列

#pragma once
namespace fx
{template <class T>class less{public:bool operator()(const T& x, const T& y) const{return x < y;}};template <class T>class greater{public:bool operator()(const T& x, const T& y) const{return x > y;}};template<class T, class Container = vector<T>, class Compare = less<T>>class priority_queue{public:priority_queue(){}template <class InputIterator>priority_queue(InputIterator first, InputIterator last):_con(first, last){for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--){adjust_down(i);}}void adjust_up(size_t child){Compare com;size_t parent = (child - 1) / 2;while (child > 0){//if ( _con[parent]<_con[child])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void adjust_down(size_t parent){Compare com;size_t child = parent * 2 + 1;while (child < _con.size()){//if (child + 1 < _con.size() && _con[child] < _con[child + 1])if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){child++;}//if (_con[parent]<_con[child])if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void push(const T& x){_con.push_back(x);adjust_up(_con.size() - 1);}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);}const T& top() const{return _con[0];}bool empty() const{return _con.empty();}size_t size() const{return _con.size();}private:Container _con;};
}

仿函数和C语言的函数指针的作用有点类似,函数指针是传入目标函数的地址,通过函数回调来执行目标函数的功能。而仿函数是一个类,对于模板函数,根据传入函数的类对象调用类中的operator()来控制不同的结果;对于模板类,通过在类中构造仿函数对象,在需要功能“分叉”的地方调用仿函数类中的operator()来达到不同的效果。(白话:泛型中的仿函数影响逻辑,通过仿函数来控制一个“水龙头”出冷水还是出热水······)

还有一种情况:优先级队列存的是某个类的地址,但是需要比较指针指向值的优先级。那这个时候就不能用中的less和greater控制建堆,需要自己写仿函数。(仿函数也可以加上模板特化)

四、 容器适配器

1.STL标准库中stack和queue的底层结构

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

在这里插入图片描述
在这里插入图片描述

2.deque(双端对列)了解

2.1deque的概念

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

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

2.2deque的缺陷

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

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

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

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

五、STL标准库中对于stack和queue的模拟实现

stack的模拟实现

#include<deque>
namespace fx
{
template<class T, class Con = deque<T>>
//template<class T, class Con = vector<T>>
//template<class T, class Con = list<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;
};
}

queue的模拟实现


include<deque>
#include <list>
namespace fx
{
template<class T, class Con = deque<T>>
//template<class T, class Con = list<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()const {return _c.size();}bool empty()const {return _c.empty();}
private:Con _c;
};
}

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

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

相关文章

OS:初识操作系统——邂逅与启航

✨ Blog’s 主页: 白乐天_ξ( ✿&#xff1e;◡❛) &#x1f308; 个人Motto&#xff1a;实践是检验真理的唯一标准&#xff01;&#xff01;&#xff01; &#x1f4ab; 欢迎来到我的学习笔记&#xff01; 前言 各位uu好&#xff0c;现在我们要开始一个新的篇章——操作…

Geneformer AI 模型,有限数据也能解锁基因网络

目录 类似于 BERT 的单单元数据参考模型 NVIDIA Clara 工具组合用于药物研发 用于疾病建模的基础 AI 模型 Geneformer 是最近推出的 和功能强大的 AI 模型&#xff0c;可以通过从大量单细胞转录组数据中进行迁移学习来学习基因网络动力学和相互作用。借助此工具&#xff0c;…

misc合集(1)

[Week3] 这是一个压缩包 有密码&#xff0c;提示QmFzZUNURj8/Pz8/P0ZUQ2VzYUI base64解密是BaseCTF??????FTCesaB 猜测这应该是⼀个轴对称的密码 python ⽣成了密码字典&#xff0c;再通过 ARCHPR 进⾏字典爆破 lowercase abcdefghijklmnopqrstuvwxyz uppercase l…

java写s7和plc通讯

pom.xml <dependency><groupId>com.github.s7connector</groupId><artifactId>s7connector</artifactId><version>2.1</version></dependency>maven下载不了的&#xff0c;下载包&#xff0c;评论或者私自内免费给 DB212 类&a…

5.1 溪降技术:个人装备

Content 5.1 个人装备概览设备概览视频电子书&#xff1a;个人装备安全装备非安全装备 峡谷探险个人安全装备个人安全装备视频*安全扣结构*峡谷探险个人非安全装备 湿峡谷湿峡谷装备视频个人安全装备个人非安全装备 干峡谷干峡谷装备视频个人安全装备个人非安全装备 团队装备&a…

安全区域边界等保测评

1.边界防护 应保证跨越边界的访问和数据流通过边界设备提供的受控接口进行通信。 [测评方法] 1)应核查在网络边界处是否部署访问控制设备;网闸和防火墙2)应核查设备配置信息是否指定端口进行跨越边界的网络通信,指定端口是否配置并启用了安全策略acl 3)应采用其他技术手…

【网盘外快】百度网盘SVIP充值使用说明,如何通过软件自动充值获取新用户优惠?这篇文章给你正确答案。

资源地址&#xff1a; 此软件需要 网盘ck 才可以使用。 雷电模拟器下载地址&#xff1a;https://www.ldmnq.com/ 软件下载地址&#xff1a;https://wwi.lanzoup.com/b01qdiavzg 密码:666 模拟器使用说明&#xff1a; 1、调整模拟器分辨率调整为&#xff1a;540 X 960。 2、…

每天练打字1:今日状况——击键5第1遍

前言 首先说明一点&#xff0c;这个每天练打打字系列不会每天更新。因为本来练打字就不是一件太大的事&#xff0c;没必要为了更新而更新&#xff0c;但还是会做到每周一更新。以便于跟踪进度&#xff0c;监控目标是否达成。 今日练习情况 一、跟打情况 常用字中五百&#…

RockyLinux-软件实现RAID5

一、背景 RAID&#xff08;Redundant Array of Independent Disks&#xff0c;独立磁盘冗余阵列&#xff09;是一种将多个物理硬盘驱动器组合成单一逻辑单元的技术&#xff0c;目的是提高存储性能、可靠性和/或数据冗余度。虽然早期的名字中包含“独立”&#xff08;Independen…

【资料分析】常见的坑

in 比较或计数类问题 差别大的基期比较&#xff0c;可以直接用现期进行比较 注意单位可能不同&#xff01; 注意顺序是从小到大还是从大到小 以及老问题&#xff0c;名字本身就叫XX增量&#xff0c;XX增加值&#xff0c;而非还要另外去算的东东 给出的图表可能是不完整的 2…

通过SQL语句判断奇偶数的几种方法

文章目录 1. 准备数据2. 使用 % 判断奇偶数3. 使用 MOD 判断奇偶数4. 使用按位与运算符 & 1. 准备数据 假设我们有一张测试表test_numbers -- 创建测试表 CREATE TABLE test_numbers (number_value INT );-- 插入测试数据 INSERT INTO test_numbers (number_value) VALUE…

Qt:饿汉单例(附带单例使用和内存管理)

前言 本文主要写饿汉单例以及单例的释放&#xff0c;网上很多教程只有单例的创建&#xff0c;但是并没有告诉我们单例的内存管理&#xff0c;这就很头疼。 正文 饿汉式单例 // SingletonClass.h #ifndef SINGLETONCLASS_H #define SINGLETONCLASS_H #include <QObject&g…

PCIe进阶之TL:First/Last DW Byte Enables Rules Traffic Class Field

1 First/Last DW Byte Enables Rules & Attributes Field 1.1 First/Last DW Byte Enables Rules Byte Enable 包含在 Memory、I/O 和 Configuration Request 中。本文定义了相应的规则。Byte Enable 位于 header 的 byte 7 。对于 TH 字段值为 1 的 Memory Read Request…

【stm32笔记】使用rtt-studio与stm32CubeMx联合创建项目

使用rtt-studio与stm32CubeMx联合创建项目 创建rt-thread项目 设置项目信息 在项目资源管理器中“右击“&#xff0c;创建RRT studio 项目 双击“RT-Thread 项目“。 选择MCU&#xff0c;设置UART&#xff0c;以及调试方式。添加项目名称&#xff0c;点击“完成“按钮。 …

长春自闭症寄宿学校:开启创造力与艺术之旅

长春自闭症寄宿学校的启示&#xff1a;在广州星贝育园&#xff0c;自闭症儿童开启创造力与艺术之旅 当我们谈及自闭症儿童的教育与成长时&#xff0c;总有一股力量在推动着我们不断探索与创新。虽然题目中提及了“长春自闭症寄宿学校”&#xff0c;但本文将聚焦于广州的星贝育…

使用jmeter做性能测试实践过程中需要注意什么

前言 在驾驭Apache JMeter进行性能测试之旅中&#xff0c;深刻理解其特性和限制是至关重要的。以下是提升JMeter效能的关键策略&#xff0c;旨在挖掘其潜力&#xff0c;克服局限&#xff0c;实现精准测试。 1.精确调控线程数 推荐阈值&#xff1a;将线程数控制在300以内&…

SSH公私钥后门从入门到应急响应

目录 1. SSH公私钥与SSH公私钥后门介绍 1.1 SSH公私钥介绍 1.1.1 公钥和私钥的基本概念 1.1.2 SSH公私钥认证的工作原理(很重要) 1.2 SSH公私钥后门介绍 2. 如何在已拿下控制权限的主机创建后门 2.1 使用 Xshell 生成公钥与私钥 2.2 将公钥上传到被需要被植入后门的服务…

AIGC技术下的动画新纪元:效率与创意的双重飞跃

文章目录 一、技术革新&#xff1a;从辅助到引领二、创作效率与质量的双重飞跃三、创新与艺术的深度融合四、挑战与展望《Procreate Dreams动画设计与制作完全解析》亮点内容简介作者简介目录 《猎头高情商沟通实务》亮点内容简介作者简介 在科技日新月异的今天&#xff0c;人工…

初始Python篇(1)——输入输出函数、数据类型、运算符

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a; Python 以B站up主&#xff1a;Python_子木的视频 &#xff1a;花了2万多买的Python教程全套&#xff0c;现在分享给大家&#xff0c;入门到精…

C++进阶 二叉搜索树的讲解

二叉搜索树的概念 二叉搜索树又称为二叉排序树。 二叉搜索树的性质 若它的左子树不为空&#xff0c;则左子树上所有结点的值都小于等于根结点的值若它的右子树不为空&#xff0c;则右子树上所有结点的值都大于等于根结点的值它的左右子树也分别为二叉搜索树二叉搜索树中可以支持…