C++容器适配器【困难篇】双向队列详解

前面我们一直说什么是容器适配器,那本片博客带你来揭晓容器适配器、deque和优先级队列。


容器适配器

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

迭代器也是一种设计模式

扩展知识设计模式有20多种类
创建型模式 (5 种)

1.单例模式 Singleton

2.工厂方法模式 Factory Method

3.抽象工厂模式 Abstract Factory

4.建造者模式 Builder

5.原型模式 Prototype


结构型模式 (7 种)

  1. 适配器模式 Adapter

  2. 桥接模式 Bridge

  3. 组合模式 Composite

  4. 装饰模式 Decorator

  5. 外观模式 Facade

  6. 享元模式 Flyweight

  7. 代理模式 Proxy


行为型模式 (11 种)

13.责任链模式 Chain of Responsibility

  1. 命令模式 Command

  2. 解释器模式 Interpreter

  3. 迭代器模式 Iterator

  4. 中介者模式 Mediator

  5. 备忘录模式 Memento

  6. 观察者模式 Observer

  7. 状态模式 State

  8. 策略模式 Strategy

  9. 模板方法模式 Template Method

  10. 访问者模式 Visitor

我们目前了解一下就好


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

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



双端队列(deque)

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

deque就是一个中控数组

如下图:

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

我们迭代器是由四个部分构成的。简单来说是四个指针

这个buff就是数组,目前不管有多大。

为啥是中控数组因为要头插数据,如果要向随机迭代器那样访问元素。

如下图:


我们两个迭代器(begin,end)一个指向第一个buff,另一个指向最后一个buff

里面的四个指针也分别指向四个元素。头插就让node减减,开辟新的buff,然后从buff的从末尾往前插入数据。为啥呢,避免头插浪费资源,那迭代器还能随机吗?

能!他是传了一个变量n,让n+(cur-fast)。来进行访问,来看看源码如下图:

他就是个指针数组,用来存放指针。


deque的缺陷

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

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

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

为什么选择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的优点,而完美的避开了其缺陷。
相关推荐
笨笨饿2 小时前
博客目录框架
c语言·开发语言·arm开发·git·嵌入式硬件·神经网络·编辑器
请数据别和我作队2 小时前
基于 DeepSeek API 的 ASR 文本纠错脚本实战:Python 多线程批量处理 JSONL 语音转写数据
开发语言·经验分享·python·自然语言处理·nlp
泡泡鱼(敲代码中)2 小时前
C++-string学习笔记
c语言·开发语言·c++·笔记·学习·visualstudio
编程大师哥2 小时前
JAVA 动态代理
java·开发语言
ytttr8732 小时前
C# 读取数据库表结构工具设计与实现
开发语言·数据库·c#
kyle~2 小时前
导航---Small-GICP重定位算法
c++·机器人·ros2·导航
Jinuss2 小时前
源码分析之React中的useImperativeHandle
开发语言·前端·javascript
WBluuue2 小时前
AtCoder Beginner Contest 451(ABCDEFG)
c++·算法
csdn2015_2 小时前
HashSet 和 LinkedHashSet 区别
java·开发语言