【C++】了解设计模式、 stackqueue的使用与模拟实现

news2024/12/26 10:54:52

文章目录

  • 1.设计模式
  • 2.stack
    • 1.stack的使用
      • 1.stack的结构
      • 2.stack的接口
    • 2.stack的模拟实现
      • 1.stack的结构
      • 2.接口实现
  • 3.queue
    • 1.queue的使用
      • 1.queue的结构
      • 3.queue的接口
    • 2.queue的模拟实现
      • 1.queue的结构
      • 2.接口实现
  • 4.了解deque
    • 1.deque的原理介绍
    • 2.deque的底层结构
    • 3.deque的迭代器设计
    • 4.deque的优缺点分析
    • 5.为什么选择deque作为stack和queue的底层默认容器

1.设计模式

设计模式(design pattern)是对面向对象设计中反复出现的问题的解决方案。这个术语是在1990年代由Erich Gamma等人从建筑设计领域引入到计算机科学中来的。这个术语的含义还存有争议。算法不是设计模式,因为算法致力于解决问题而非设计问题。设计模式通常描述了一组相互紧密作用的类与对象。设计模式提供一种讨论软件设计的公共语言,使得熟练设计者的设计经验可以被初学者和其他设计者掌握。设计模式还为软件重构提供了目标。

总之,设计模式就是为了解决某类重复出现的问题而出现的一套成功或有效的解决方案

设计模式一共有23种,目前我们接触到的设计模式主要就是迭代器模式(Iterator Pattern)

迭代器模式:迭代器封装之后,提供一种方法顺序访问一个聚合对象中各个元素,不暴露底层细节

那么从本文开始,我们要接触到一个新的设计模式——适配器模式(Adapter Pattern)

适配器模式:适配器实际上是一种转换,将一个类的接口转换成客户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类可以一起工作

2.stack

1.stack的使用

1.stack的结构

image-20230425142636684

image-20230425142948683

可以看到模板参数和我们之前看到的list,vector不同,stack的第二个模板参数是一个容器,在下面的介绍中也能看到,stack是一种容器适配器。本质上就是为这种容器提供一类特定的接口

2.stack的接口

image-20230425143534300

可以看到,stack的接口比容器的接口少了很多。这些接口使用起来很容易,所以这里就不做示范了。如果需要查看接口的详细信息,这里还是推荐cplusplus.com

接口说明
stack构造一个空栈
empty判断栈是否为空,返回bool类型
size返回栈中元素个数,size_t类型
top返回栈顶元素
push压栈
pop出栈

2.stack的模拟实现

1.stack的结构

在上文中我们看到stack类模板的模板参数有两个,第一个是存放元素类型,第二个是容器类型,这里容器类型我们与库里面的实现保持统一,默认容器是deque,后文将会介绍deque这个容器

stack这个类中,由于使用了容器,所以在成员变量中,只需要一个容器对象用于存放数据即可,所以结构如下

namespace zht//这里把实现的stack包在命名空间中
{
	template<class T, class Container = std::deque<T>>
	class stack
	{
	public:
		//成员函数
	private:
		Container _con;
	};
}

2.接口实现

按照上述接口的介绍,我们实现一下上述的重点接口。由于stack是使用了其他容器的,所以我们直接调用该容器的接口即可

//构造函数:我们不显示写,编译器生成。直接调用_con的默认构造
bool empty() const
{
    return _con.empty();
}
size_t size() const
{
    return _con.size();
}
const T& top() 
{
    return _con.back();//适配这类操作的容器都是支持back或者front接口的,直接调用即可
}
void push(const T& val)
{
    _con.push_back(val);
}
void pop()
{
    _con.pop_back();
}

3.queue

1.queue的使用

1.queue的结构

image-20230425191254715

与stack相同,queue也是一个容器适配器,但是和stack的规则不相同,stack是后进先出:LIFO,queue是先进先出:FIFO

3.queue的接口

image-20230425200154440

和stack很相似的接口,就不一一解释了,如果有需要,可以去cplusplus.com查看详细文档.

2.queue的模拟实现

1.queue的结构

和stack的结构非常相似,代码框架如下:

namespace zht//这里把实现的queue包在命名空间中
{
	template<class T, class Container = std::deque<T>>
	class queue
	{
	public:
		//成员函数
	private:
		Container _con;
	};
}

2.接口实现

queue的接口实现方式和queue也是非常的类似,唯一需要改的就是push和pop数据的位置

//构造函数:我们不显示写,编译器生成。直接调用_con的默认构造
bool empty() const
{
    return _con.empty();
}
size_t size() const
{
    return _con.size();
}
const T& top() 
{
    return _con.back();//适配这类操作的容器都是支持back或者front接口的,直接调用即可
}
void push(const T& val)//这里的push我们采用尾插的方式插入
{
    _con.push_back(val);
}
void pop()//由于push使用的是尾插,所以pop采用头删的方式
{
    _con.pop_back();
}

至此,我们就算是能够手撕stack和queue了哈哈。

4.了解deque

我们注意到,stack和queue的容器都是deque。这是为什么呢?在学习数据结构的时候,实现的stack和queue一般是使用顺序表和链表实现的。为什么这里不使用vector和list呢?

vector和list的结构都存在一些缺陷:vector真正的缺点在于扩容消耗,不支持头插头删,因为头部中部删除效率低。而list不支持随机访问,且CPU高速缓存命中率低,空间不连续。而deque兼具了vector和list的优点,虽然deque也有很多缺点,但是作为适配器的容器恰好避免了这些。

对于deque,我们稍微了解一下即可,因为deque合适的使用场景很少。

1.deque的原理介绍

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

image-20230425214336807

这只是逻辑图,deque在底层并不是真的连续空间

2.deque的底层结构

deque的底层是由很多段连续的小空间拼接而成类似一个二维数组,然后这些小空间的地址存放在一个中控指针数组中。结构示意图如下:

image-20230425220139343

3.deque的迭代器设计

那么deque是如何使用迭代器来维护这个假想的连续结构的呢?

这里参考一下侯捷老师的STL源码剖析中的图:

image-20230425220410116

deque的迭代器包含四个指针,其中cur指向当前值,first和last指向当前cur所在的小段连续空间,node指向中控数组中存放所在连续空间的地址。

4.deque的优缺点分析

优点:头部插入和删除时,不需要搬移元素,效率特别高,扩容时,也不需要搬移大量的元素,因此其效率是比vector高的。与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段。

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

5.为什么选择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不仅效率高,而且内存使用率高。
  3. 结合了deque的优点,而完美的避开了其缺陷

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

  1. stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。
  2. 在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。
  3. 结合了deque的优点,而完美的避开了其缺陷

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

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

相关文章

Codeforces Round 861 (Div. 2)(A~D)

A. Lucky Numbers 给出边界l和r&#xff0c;在区间[l, r]之间找到幸运值最大的数字。一个数字的幸运值被定义为数位差的最大值&#xff0c;即数字中最大的数位和最小的数位的差。 思路&#xff1a;因为涉及到至少两位&#xff0c;即个位和十位变化最快&#xff0c;最容易得到相…

Android四大组件之广播接收者BroadcastReceiver

一、全局广播 Android中的广播可以分为两种类型&#xff1a;标准广播和有序广播 标准广播&#xff1a;一种完全异步执行的广播&#xff0c;在广播发出之后&#xff0c;所有的广播接收器几乎都会同一时刻接收到这条广播消息&#xff0c;因此它们之间没有任何先后顺序。无法进行…

Vector-常用CAN工具 - 入门到精通 - 专栏链接

一、CANoe篇 1、CANoe入门到精通_软件安装 2、CANoe入门到精通_硬件及环境搭建 3、CANoe入门到精通_软件环境配置 4、CANoe入门到精通_Network Node CAPL开发 5、CANoe入门到精通_Node节点开发基本数据类型 6、CANoe入门到精通_Test Node节点开发设置 7、CANoe入门到精通…

《Cocos Creator游戏实战》AIGC之将草稿内容转为真实内容

目录 前言 训练AI 从识别结果中提取必要数据 发送图片并生成最终代码 总结与提高 资源下载 前言 当创作灵感来的时候&#xff0c;我们可能会先把灵感记录在草稿上&#xff0c;之后再去实现它。比方说有一天&#xff0c;我突然来了游戏创作灵感&#xff0c;想着那可以先把…

gpt 怎么用-免费gpt下载使用方法

gpt 怎么用 GPT&#xff08;Generative Pre-trained Transformer&#xff09;是一种基于Transformer的神经网络模型&#xff0c;用于自然语言处理任务&#xff0c;例如文本生成、摘要生成、翻译、问答等。以下是使用GPT进行文本生成的一般步骤&#xff1a; 首先&#xff0c;您…

编译预处理

编译预处理 1、宏定义1.1、 无参宏定义1.2、使用宏定义的优点1.3、宏定义注意点1.4、带参数的宏(重点)1.5、条件编译1.6、宏定义的一些巧妙用法(有用)1.7、结构体占用字节数的计算原则&#xff08;考题经常考&#xff0c;要会画图&#xff09;1.8、#在宏定义中的作用&#xff0…

转型产业互联网,新氧能否再造辉煌?

近年来&#xff0c;“颜值经济”推动医美行业快速发展&#xff0c;在利润驱动下&#xff0c;除了专注医美赛道的企业之外&#xff0c;也有不少第三方互联网平台正强势进入医美领域&#xff0c;使以新氧为代表的医美企业面对不小发展压力&#xff0c;同时也展现出强大的发展韧性…

六、CANdelaStudio入门-通信参数编辑

本专栏将由浅入深的展开诊断实际开发与测试的数据库编辑,包含大量实际开发过程中的步骤、使用技巧与少量对Autosar标准的解读。希望能对大家有所帮助,与大家共同成长,早日成为一名车载诊断、通信全栈工程师。 本文介绍CANdelaStudio的通信参数编辑,欢迎各位朋友订阅、评论,…

Kubernetes 笔记(16)— 集群管理、使用名字空间分隔系统资源、给名字空间设置资源限额、默认资源配额的使用

1. 为什么要有名字空间 首先要明白&#xff0c;Kubernetes 的名字空间并不是一个实体对象&#xff0c;只是一个逻辑上的概念。它可以把集群切分成一个个彼此独立的区域&#xff0c;然后我们把对象放到这些区域里&#xff0c;就实现了类似容器技术里 namespace 的隔离效果&…

MATLAB符号运算(七) 更新中...

目录 1、实验目的&#xff1a; 2、实验内容&#xff1a; 1、实验目的&#xff1a; 1&#xff09;掌握定义符号对象和创建符号表达式的方法&#xff1b; 2&#xff09;掌握符号运算基本命令和规则&#xff1b; 3&#xff09;掌握符号表达式的运算法则以及符号矩阵运算&#xf…

93、Dehazing-NeRF: Neural Radiance Fields from Hazy Images

简介 论文&#xff1a;https://arxiv.org/pdf/2304.11448.pdf 从模糊图像输入中恢复清晰NeRF 使用大气散射模型模拟有雾图像的物理成像过程&#xff0c;联合学习大气散射模型和干净的NeRF模型&#xff0c;用于图像去雾和新视图合成 通过将NeRF 3D场景的深度估计与大气散射模…

【牛客刷题专栏】23:JZ22 链表中倒数最后k个结点(C语言编程题)

前言 个人推荐在牛客网刷题(点击可以跳转)&#xff0c;它登陆后会保存刷题记录进度&#xff0c;重新登录时写过的题目代码不会丢失。个人刷题练习系列专栏&#xff1a;个人CSDN牛客刷题专栏。 题目来自&#xff1a;牛客/题库 / 在线编程 / 剑指offer&#xff1a; 目录 前言问…

LeetCode-344. 反转字符串

题目链接 LeetCode-344. 反转字符串 题目描述 题解 题解一&#xff08;Java&#xff09; 作者&#xff1a;仲景 直接双指针前后一直交换即可 class Solution {public void reverseString(char[] s) {if (s.length 1)return;// 双指针int lp 0, rp s.length - 1;while (lp…

【百度智能云】基于http3的xcdn 开放直播方案设计与实践

大神:柯老师 现有的融合CDN 0 需要集成sdksdk 是集成在端侧缺点 sdk 对端侧有影响多云模式下,sdk不互通、 XCDN 设计目标 :保持现有cdn的优势 承载各种业务:直播点播让各家的cdn互通cdn 厂家屏蔽了差异性,集成起来比较简单,对接简单开发的互联网生态。使用统一的http3标…

理解缓冲区

文章目录 一.缓冲区1.什么是缓冲区2.缓冲区的意义3.缓冲区的刷新策略4.我们目前谈论的缓冲区在哪里5.仿写FILE5.1myStdio.h5.2myStdio.c 6.操作系统的缓冲区 一.缓冲区 int main() {printf("hello linux");sleep(2);return 0; }对于这样的代码&#xff0c;首先可以肯…

C++11 unique_ptr智能指针

#include<iostream> using namespace std;class test { public:test() {cout << "调用构造函数" << endl;}~test() {cout << "调用析构函数" << endl;} };int main(void) {//1.构造函数unique_ptr<test>t1;unique_ptr…

数据结构之KMP算法:彻底搞懂kmp算法

数据结构的学习&#xff0c;kmp匹配算法困扰我许久&#xff0c;此处来一个总结&#xff08;仅供自己复习了解参考使用&#xff09;&#xff0c;如果有不对的地方请多多指点。好了废话不多说我们直接开始好吧。 目录 关于暴力匹配原理的讲解&#xff1a; kmp算法&#xff1a; …

ChatGPT - 如何高效的调教ChatGPT (指令建构模型-LACES问题模型)

文章目录 定义1. Limitation&#xff08;限定条件&#xff09;2. Assignment&#xff08;分配角色&#xff09;3. Context&#xff08;背景或上下文&#xff09;4. Example&#xff08;示例&#xff09;5. Step by Step&#xff08;拆分任务&#xff09; 小Demo 定义 LACES问题…

尚硅谷大数据技术Spark教程-笔记04【SparkCore(核心编程,RDD-行动算子-序列化-依赖关系-持久化-分区器-文件读取与保存)】

视频地址&#xff1a;尚硅谷大数据Spark教程从入门到精通_哔哩哔哩_bilibili 尚硅谷大数据技术Spark教程-笔记01【Spark&#xff08;概述、快速上手、运行环境、运行架构&#xff09;】尚硅谷大数据技术Spark教程-笔记02【SparkCore&#xff08;核心编程&#xff0c;RDD-核心属…

加强人工智能共性技术研发与产业化协同发展

央视网消息&#xff1a;“以5G为代表的新一代信息技术与制造业、交通、旅游等实体经济重要领域深度融合。”4月20日下午&#xff0c;国新办举行一季度工业和信息化发展情况新闻发布会&#xff0c;相关部门负责人在答问时表示&#xff0c;将用好融合应用这把金钥匙&#xff0c;开…