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

embedded/2024/9/24 2:50:56/

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.ppmy.cn/embedded/115864.html

相关文章

颍川陈氏——平民崛起的典范

园子说颍川 广州有一处老建筑“陈家祠”,豪华精美堪比皇宫,誉为“岭南建筑艺术明珠”、“新世纪羊城八景”之一,是全国文保单位,4A 级景区。主体建筑以中轴线三座厅堂为中心,由大小十九座单体建筑组成,占地…

PHP校园外卖跑腿小程序带后台(商业版)

有需要请加文章底部Q哦 可远程调试 PHP校园外卖跑腿小程序带后台(商业版) 一 介绍 此校园外卖跑腿小程序端基于原生开发,后端基于ThinkPHP5框架开发,数据库mysql,系统角色分为用户,商家(自配送),跑腿员,管…

【TypeScript】 数据类型

文章目录 数据类型1. TypeScript Number进制表示:常用的内置属性:常用的内置方法: 2. TypeScript String字符串的创建:常用的内置属性和方法: 3. TypeScript Array数组的声明与使用:常用的内置属性和方法&a…

罗德岛战记游戏源码(客户端+服务端+数据库+全套源码)游戏大小9.41G

罗德岛战记游戏源码(客户端服务端数据库全套源码)游戏大小9.41G 下载地址: 通过网盘分享的文件:【源码】罗德岛战记游戏源码(客户端服务端数据库全套源码)游戏大小9.41G 链接: https://pan.baidu.com/s/1y0…

Django 创建好的模块怎么在后台显示

1、配置模型及其需要显示的数据 刚才创建好的tests的增删改查,在后台是不显示的,所以需要进行配置,在刚才创建好的模块里找到admin.py文件,在里面进行如下配置 from django.contrib import adminfrom . import models from .models import …

“跨链桥“的危害

跨链桥(Cross-Chain Bridges)是连接不同区块链网络的工具,允许用户在不同的区块链之间转移资产和数据。尽管跨链桥为区块链生态系统带来了许多便利,但它们也存在一些潜在的危害和风险。以下是一些主要的危害: 1. 安全…

【算法】堆与优先级队列

【ps】本篇有 4 道 leetcode OJ。 目录 一、算法简介 二、相关例题 1)最后一块石头的重量 .1- 题目解析 .2- 代码编写 2)数据流中的第 K 大元素 .1- 题目解析 .2- 代码编写 3)前K个高频单词 .1- 题目解析 .2- 代码编写 4&#xf…

Java-ArrayList和LinkedList区别

⾸先,他们的底层数据结构不同,ArrayList底层是基于数组实现的,LinkedList底层是基于链表实现的由于底层数据结构不同,他们所适⽤的场景也不同,ArrayList更适合随机查找,LinkedList更适合删除和添加&#xf…