【STL】容器适配器

news/2025/3/4 12:42:58/

 放在专栏【C++知识总结】,会持续更新,期待支持


1、什么是适配器?

我们生活中就存在大量的适配器,最常见的莫过于我们常见的电源适配器,它的作用就是将交流电源转化为直流电源进行输出,可以说电源适配器在电流转换之间扮演着一个轴承、转换器的角色。

1.1、适配器概念

适配器(也称之为配接器adapter)作为STL的六大组件之一,在STL中同样扮演轴承、转换器的角色。adapter这个概念实际上是一种设计模式:将一个class的接口转化为另一个class的接口,使原本因接口不兼容而不能合作的classes可以一起合作。

就比如马上就要讲的,stack的相关操作底层实际上是调用了deque的对应的函数接口,或者queue的相关操作我们也可以实现成在底层调用list的对应的接口。具有这种将一个类的接口转化成客户想要的另一个类的接口的性质的,我们称之为适配器(配接器)。

2、STL中的适配器

2.1、适配器分类

在STL所提供的各种适配器中,改变仿函数接口者,我们称之为函数适配器(function adapter);改变容器接口者称之为:容器适配器(container adapter);改变迭代器接口者,称之为迭代器适配器(iterator adapter)。本章我们讲的主要是容器适配器。

2.2、stack

2.2.1、stack介绍

stack是一种先进后出(FILO -> First In Last Out)的数据结构,只具有一个出入口,如下图所示:

 我们查阅文档就可以发现,stack是以deque作为其底层容器,也就是说,stack的push、pop、top等相关操作,其实底层都是调用的deque的相关接口,这也是为什么stack被归类为适配器而非容器的原因所在。至于为何采用deque作为其底层容器,本文后面会进行讲解。

2.2.2、stack使用

在使用时,我们平常并不需要修改其底层容器,只需传一个模板参数类型即可,使用时需包含头文件<stack>。如下所示:

 当然,我们也可以更换其底层容器,不过有一点需要注意的是,作为栈的底层容器必须要支持以下几个操作:

  • empty        : 判空
  • size            :有效元素个数
  • back           :尾部元素
  • push_back :尾插
  • pop_back   :尾删

因此,诸如vector、list都可以作为其底层容器:

stack的常用接口也非常的少,基本上常用的就是以上我所讲的一些。接下来我们来模拟实现一个stack。

2.2.3、stack的模拟实现

这里我们也可以按库中那样,默认以deque作为其底层容器来实现,不过这里我们换一个底层容器,用vector来实现,模拟实现也很简单,全都是用底层容器的接口来完成:

2.3、queue

2.3.1、queue的介绍

queue也是默认以deque作为其底层容器,我们平常在使用时,直接传一个模板参数T即可,当然我们也可以修改其底层容器,不过要作为queue的底层容器,必须要具有以下几个接口:

  • empty         :判断是否空
  • size            :有效元素个数
  • front           :获取头部元素
  • back           :获取尾部元素
  • push_back :尾插
  • pop_front    :头删

queue是一个先进先出(FIFO,First In Firet Out)的数据结构,其从一端插入元素,从另一端删除元素。

2.3.2、queue的使用

 queue的使用也很简单,在使用之前要包含头文件<queue>:

 2.3.3、queue的模拟实现

这里我们来模拟一个以list为底层容器的链式队列,queue的接口底层通通调用list对应的接口来实现:

 3、deque双端队列(了解即可)

3.1、deque介绍

deque是一个双端队列,可以实现在头尾两端的相关操作,并且在头尾两端的操作十分高效。与vector相比,vector虽然也可以实现在头部的操作,但实现起来比较复杂,要挪动后面的所有元素,而与list相比,由于其底层空间是连续空间,所以空间利用率要高于list,并且list不支持下标的随机访问,而deque则支持。

因此,可以说deque是集合了list与vector各自的优点(头尾高效操作+随机访问元素),但是自古以来鱼与熊掌不可兼得,deque虽集合了各自的优点,但是却做不到vector与list那么极致。deque的数据结构较为复杂,尤其是其迭代器。不过作为一个容器适配器来说,我们仅仅需要其头尾两端/或者一端的中间的插入删除相关操作。接下来我们来看一下它的结构。

3.2、deque的结构

3.2.1、deque的基本介绍

 如上图所示,deque采用map作为主控,这里的map并非STL容器中的map,这里的map是一小块连续的空间,每个元素都是一个指针(数组指针),该指针指向了一块缓冲区,这里的缓冲区用来deque存储数据。(有点类似于二维数组vector<vector<T>>)。

3.2.2、deque的迭代器

deque的迭代器设计十分复杂,如下所示:

 这里迭代器中的node指向中控器中的node节点,其first与last分别指向node指向的缓冲区的起始位置以及最后一个位置,cur则指向当前所在缓冲区的位置,++或者--进行对缓冲区内的数据遍历,当cur指针指向last位置时,此时的++或--则是指向中控器中的下一个node节点。因此我们看到deque的结构确实复杂,其遍历操作效率低下,因为每一次的++或--操作,都要检测迭代器是否指向缓冲区的两端。

3.2.3、deque的扩容机制

相比于vector,vector的扩容是分为3步走,开辟更大一块空间->将原空间数据进行拷贝->释放原有空间,这里的拷贝如果vector存储的是自定义类型,其中还要涉及深拷贝,而deque由于其中控器中存储的都是一个个的指针,因此在扩容时,仅仅只需要将其数组指针进行拷贝,这里就不存在深拷贝的问题,因为指针是内置类型,内置类型在拷贝时是值拷贝(浅),因此deque的扩容要比vector高效的多。

3.2.4、deque的随机访问

deque虽然支持随机访问,但是其效率也是不如vector的,这里假如我们第一个缓冲区已经存在了3个数据,且每一个缓冲区的大小固定为10,这里我们要想实现访问第25个数据,在vector中则只需要vector[24]即可访问到该数据,而在deque中则需要:1、先找到其所在的缓冲区。2、再找到在缓冲区的第几个位置。

这里则是(25-3)/10:找到在第几个缓冲区,(25-3)%10,找到其在缓冲区的第几个位置。我们可以看到,缓冲区的大小会影响其随机访问的效率,所以在SGI版本下,为了提高随机访问的效率,其缓冲区的大小都是固定不变的。

 3.2.5、为什么采用deque作为stack与queue的默认底层容器?

这是因为对于stack来说,只要具有尾部操作的容器都可以作为其底层容器,比如list与vector,而queue只要具有头尾两端相关操作的容器,都可以作为其底层容器,诸如list。但是这里为何要采用deque呢?因为首先,deque的两端操作都很高效,达到了O(1)的时间复杂度,再接着deque的扩容也要比vector更加高效,并且空间由于是连续的,所以空间利用率要高于list。虽然说deque的遍历,以及在中间位置相关操作的效率不如list与vector,但是stack与queue并不需要遍历的相关操作,也不需要在中间位置插入删除,仅仅只需要其两端操作。所以deque作为其默认底层容器,完美的避开了deque的所有缺点,而又很好的利用了其优点。


end.

生活原本沉闷,但跑起来就会有风!🌹


http://www.ppmy.cn/news/585094.html

相关文章

[算法前沿]--022-Pytorch从0编写Transformer算法

文章目录 预备工作背景模型架构Encoder部分和Decoder部分EncoderDecoderAttention模型中Attention的应用基于位置的前馈网络Embeddings and Softmax位置编码完整模型训练批处理和掩码Training Loop训练数据和批处理硬件和训练时间Optimizer正则化标签平滑实例<

Ansys Zemax | 内窥镜物镜系统初始结构的优化提升(下)

系统性能提升 根据上篇的内窥镜系统分析&#xff0c;我们可以从四个方面对内窥镜物镜系统进行优化&#xff1a;元件间距、圆锥系数、MTF 值以及畸变值。点击优化-评价函数编辑器以设置具体的评价函数。&#xff08;联系我们获取文章附件&#xff09; 首先&#xff0c;用三个 CO…

4K、2K、1080p、720p、480p、240p常见视频清晰度

记录自用 一、清晰度对应的格式 标号视频类型格式尺寸类型比例14K4096*21604K16:922K2560*14402K16:93全高清1920*10801080p16:94高清1280*720720p16:95标清720*480480p3:26标清640*480480p4:37流畅320*240240p​4:3 注&#xff1a; 字母P意为逐行扫描 多数情况下4k特指4096…

BD,HD,720P和1280P的区别

BD是蓝光光碟&#xff08;Blu-ray Disc&#xff0c;简称BD&#xff09;&#xff0c;是DVD之后的下一代光盘格式之一&#xff0c;用以存储高品质的影音以及高容量的数据存储。 HD是英文High Definition的简称&#xff0c;是指垂直分辨率大于等于720的图像或视频&#xff0c;也称…

视频模糊如何转高清?

现在关于视频模糊转高清的方法很多很多&#xff0c;一些工具软件又过于专业不好学习使用&#xff0c;得益于人工智能技术的进步&#xff0c;已经有了更简单快捷的方法实现模糊视频转高清超分辨补帧&#xff0c;大家不妨试试。 1.什么是高清视频格式&#xff1f; 视频文件格式…

看视频常见的 720p、1080p、4k,这些分辨率到底包含了什么

从早期的420p&#xff0c;到后来的720p&#xff0c;到现在的非1080p不看。视频的清晰度飞快提升&#xff0c;但是在看到色彩越来越丰富清晰度越来越高的画面时&#xff0c;你有关注过他们的到底是怎么做到的么&#xff1f;我们一起来了解一下吧。 想必大家在日常生活中都会看到…

1080P和720P视频分辨率到底是多少

我们常说到1080P和720P这些视频尺寸&#xff0c;但对于这个尺寸&#xff0c;其分辨率到底是多少呢&#xff1f;通常来说1080P就是1920x1080&#xff08;宽x高&#xff09;&#xff0c;720P就是1280x720&#xff0c;因为肉眼对横向分辨率更敏感&#xff0c;所以&#xff0c;拥有…

高清分辨率4K到底咋算的,720P,1080P又是啥意思?

既然说到这了&#xff0c;哪咱们就说说&#xff0c;4K到底意味着什么呢&#xff1f; 它比超高清(Ultra HD)的像素还要多吗&#xff1f; 如果4K是1080p的四倍&#xff0c;那是否意味着4K就等于4320p&#xff1f; 以上三个问题按顺序回答&#xff1a;视情况而定&#xff1b;有…