[c++进阶(九)] STL之deque深度剖析

1.前言

本章重点

本章将会着重的介绍deque底层到底是如何实现它能够双向进出的,并且双向进出的消耗率还特别低,并且讲解deque的优缺点。

2.deque的使用

如果没有看我前面两篇文章的,请先看前面两篇文章再来看这篇文章,可以有助于理解。

[c++进阶(八)]STL容器适配器之queue-CSDN博客

[c++进阶(七)]STL容器适配器之stack-CSDN博客

deque在stack和queue里面使用的是deque作为底层容器,但是为何用的是deque呢?他有什么优势呢?又有什么缺点呢?

3.deque的原理

1.deque的结构

deque的底层结构是双端队列,这种队列可以实现双开口进出,并且进出的时间复杂度为0(1)。

与vector相比:头插的更加方便

与list相比:空间连续,空间利用率更高。

2.deque的底层结构

(1)deque的底层空间

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

中控指针数组中存放的是指向缓冲区buffer的指针,是动态开辟的二维数组,先malloc一个指针数组,指针数组的每个位置存放一维数组buffer的地址。当deque不断开buffer时,map中控指针数组满了,那么会增容,不过map增容的代价非常低,因为只需要拷贝存储数据的buffer数组的指针,不需要拷贝buffer中的内容。

如果要计算要访问的元素在第几个buffer里面,每个buffer固定大小,i/buffer.size()+1算出在第几个buffer中,i%buffer.size()算出是buffer中的第几个元素。

(2)deque是如何支持随机访问

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

first指向buffer的第一个位置,last指向最后一个位置,cur指向当前buffer中存在的数据,node则需要回指导中控指针数组。

为什么要指回呢?这是因为当迭代器遍历到当前为止时,如果需要++或者--,自己是无法找到下一个buffer在那个位置,必须根据中控指针的指向找到下一个需要遍历的位置,所以说需要一个node来回指中控指针,方便迭代器迭代。

(3)deque迭代器

那deque是如何借助其迭代器维护其假想连续的结构呢? 如果一个buffer走完了,如何走到下一个buffer的位置呢?用node++来控制,node反向指向map当中当前buffer的位置,那么node++就指向下一个node的位置,解引用就是下一个buffer的位置。

node并不是从第一个位置就开始存放的,从中间开始存放,那么头插就还有空余位置。

而在buffer中存放位置一般都是从尾部开始存放的,这样就方便后续的头插头删,尾插尾删等相关操作了。

3.deque的缺陷

deque不适合随机访问,不适合中间插入和删除函数。可以说他结合了vector和list的相关特性。

可以说deque的优缺点也和vector和list的优缺点息息相关。

(1)deque的致命缺陷

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

(2)deque的优点

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

4.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作为底层默认容器,不仅效率高,而且内存使用率高。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

手写Spring第三篇,原来Spring容器是使用反射来初始化对象的

上次是不是你小子和大家说你拿来做登记的样品被我收了,然后取豆子的时候就是这个样品的? 今天我来辟一下谣,真的是这样的。这小子的样品确实被我收了,不过这小子没给真东西给我,只给了一个指针,害我宝贝得存…

Git rebase 的使用(结合图与案例)

目录 Git rebase 的使用Git rebase 概念Git rebase 原理rebase和merge的选择 Git rebase 的使用 在 Git 中整合来自不同分支的修改主要有两种方法:merge 以及 rebase Git rebase 概念 **rebase概念:**用来重新应用提交(commits&#xff09…

Llama 3.1 技术研究报告-1

llama3模型 现代⼈⼯智能(AI)系统由基础模型驱动。本⽂介绍了⼀组新的基础模型,称为Llama 3。它是⼀个语⾔模型群,原⽣⽀持多语⾔性、编码、推理和⼯具使⽤。我们最⼤的模型是⼀个密集变换器,有 405B个参数&#xff0…

oracle 插入date日期类型的数据、插入从表中查出的数据,使用表中的默认数据

date sysdate to_date 插入从表中查出的数据 方式一 方式二 或者指定列名称 下边这个案例的前提是指定列插入,如果不指定,则也是默认的

消息中间件---Kafka

一、什么是Kafka? Kafka是一个分布式流处理平台,类似于消息队列或企业消息传递系统; 流处理事什么呢? 流处理就是数据处理工作流,本质上是一种计算机编程范例。流处理是对接收到的新数据事件的连续处理。‌它涉及对从生产者到消…

HTML+CSS学习笔记

目录 HTML 1.开发环境 2.创建HTML文件 3.HTML元素 3.1HTML文件结构 3.2HTML标签 3.3HTML属性​编辑​编辑 3.4HTML区块 3.4.1块元素 3.4.2行内元素 3.5HTML表单 CSS 1.CSS简介 2.CSS语法​编辑 3.CSS三种导入方式 内联样式 内部样式 外部样式 4.选择器​ 5.C…

9月23日

思维导图 作业 统计家目录下.c文件的个数 #!/bin/bashnum0for file in ~/*.c; doif [ -f "$file" ]; then((num))fi doneecho "家目录下.c文件的个数: $num"

本周宣讲提醒-线上专场——香港科技大学工学院2025/2026年度硕士研究生(MSc)项目招生宣讲会

📆本周宣讲提醒-线上专场 🔔香港科技大学工学院2025/2026年度硕士研究生(MSc)项目招生宣讲会 📍香港科技大学工学院大挑战研究暨研究生课程信息网络研讨会-线上专场 🕙时间:2024年9月24日&…

python爬虫中json和xml字符串的xPath和jsonpath过滤语法区别对比

参考博客 两种语法结构作用 为了处理从网络请求返回的网页源码中得到自己想要的数据 首先了解两种库处理的对象语法 jsonpath处理的是json语法格式的字符串 **json(JavaScript Object Notation)**字符串的语法参考 **类似于下面的格式,以…

【VUE3.0】动手做一套像素风的前端UI组件库---先导篇

系列文章目录 【VUE3.0】动手做一套像素风的前端UI组件库—Button【VUE3.0】动手做一套像素风的前端UI组件库—Radio 目录 系列文章目录引言准备素材字体鼠标手势图 创建vue3项目构建项目1. 根据命令行提示选择如下:2. 进入项目根目录下载依赖并启动。3. 设置项目s…

MySQL函数介绍--日期与时间函数(二)

我相信大家在学习各种语言的时候或多或少听过我们函数或者方法这一类的名词,函数在计算机语言的使用中可以说是贯穿始终,那么大家有没有思考过到底函数是什么?函数的作用又是什么呢?我们为什么要使用函数?其实&#xf…

什么是上层封禁海外流量

上层封禁海外流量(Upper-layer Blocking of Overseas Traffic)是一种网络安全策略,旨在通过在网络传输的上层进行流量控制和过滤,从而阻止来自海外的恶意流量或不必要的访问。这一措施主要用于防止分布式拒绝服务(DDoS…

【AIGC】ChatGPT RAG提取文档内容,高效制作PPT、论文

目录 一、理解 RAG 技术 二、利用 ChatGPT 的 RAG 技术提取文档内容 三、高效制作 PPT 四、高效撰写论文 五、最佳实践与建议 六、工具推荐 随着人工智能生成内容(AIGC)的快速发展,利用先进的技术工具如 ChatGPT 的 RAG(Ret…

【深度学习】(3)--损失函数

文章目录 损失函数一、L1Loss损失函数1. 定义2. 优缺点3. 应用 二、NLLLoss损失函数1. 定义与原理2. 优点与注意3. 应用 三、MSELoss损失函数1. 定义与原理2. 优点与注意3. 应用 四、BCELoss损失函数1. 定义与原理2. 优点与注意3. 应用 五、CrossEntropyLoss损失函数1. 定义与原…

【觅图网-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…

Java集合(Map篇)

一.Map a.使用Map i.键值(key-value)映射表的数据结构,能高效通过key快速查找value(元素)。 ii.Map是一个接口,最常用的实现类是HashMap。 iii.重复放入k-v不会有问题,但是一个…

Rasa对话模型——做一个语言助手

1、Rasa模型 1.1 模型介绍 Rasa是一个用于构建对话 AI 的开源框架,主要用于开发聊天机器人和语音助手。Rasa 提供了自然语言理解(NLU)和对话管理(DM)功能,使开发者能够创建智能、交互式的对话系统。 1.2…

【计算机网络】计算机网络基础二

🍑个人主页:Jupiter. 🚀 所属专栏:Linux从入门到进阶 欢迎大家点赞收藏评论😊 目录 以太网的通信原理令牌环网的通信原理网络传输基本流程 数据包封装和分用 网络传输流程图 局域网通信(同一个网段内的两台…

Java基础笔记1】Java基础语法

目录 一、Java简介 二、JDK和Java初体验 三、配置环境变量 四、IDEA快捷键 五、Java语法基础 1. 注释 2. 字面量 3. 变量 4. 关键字和标识符 5. 变量详解 a. 数值数据在计算机中的存储​编辑 b. 文本、图片、音频等数据在计算机中的存储 c. 八进制和十六进制 6. 数据类型 a. …

Java多线程(1)—线程基础

一、关于线程 1.1 简介 计算机线程(Thread)是操作系统能够进行运算调度的最小单位。线程的优势在于提高了程序的效率和响应能力,尤其在处理 I/O 操作或多任务时。多线程编程能够充分利用多核处理器的计算能力,达到更高的性能。 …