3.使用
4.参考
0.概述
什么是deque呢?
一句话来概括 ,deque是一种 双向开口的"连续"线性空间存储数据的数据结构(注意这里的连续打了双引号,后面会解释)
咱们来对比一下deque和vector的一些区别
优点:
1.vector是单向开口 deque是双向开口.也就是说vector只能在一端插入和删除数据,而deque在两端都可以插入和删除数据
(其实vector也可以在头部插入和删除,但是头部插入,后面的元素就得后移,所以效率奇差,一般不采用)
2.如第一条所说,vector在头部插入删除元素效率很低,但是deque在头部插入和删除元素是常数时间.
3.vector是一端连续线性空间,满了以后,在重新分配空间 搬运元素,回收原来空间.但是deque的连续线性空间的"连续"其实是一种假象,实际上他是动态的以分段连续空间组合而成的(这一点到后面会有讲解),所以deque没有必要提供空间保留功能
缺点:
1.vector和deque的迭代器都属于Random Acess Iterator ,且vector的迭代器本质上就是指针,而deque由于结构的复杂性,他的迭代器也会相应复杂得多,从而也影响了一些deque成员函数计算复杂性,所以一般可以用vector的地方尽量用vector.比如要对deque的元素排序时,为了提高效率,一般会把deque元素复制到vetor然后在vector里面排好序复制回deque.
下面将通过源码 分几个部分来讲解deque
1. 中控器与迭代器
-
原理讲解
现在来说一下为什么deque的连续是一种"假象"
deque本质上是由一段一段小的连续子空间拼在一起的,
当要在deque已满的情况下在尾部插入元素,deque会在尾部再加入一段小的连续子空间.
同样在deque已满的情况下在头部插入元素,deque会在头部再加入一段小的连续子空间.
然后通过某种办法来把这些分段的连续子空间维护其整体连续的假象.这个办法就是 中控器.
这样就避免了vector每次空间满了以后的"重新配置,搬运元素 回收内存"的麻烦 带来了上一节所说的三个优点
同时由于设计相对会复杂一点,所以就导致了deque实现复杂度会大很多.
下面来具体讲一讲整体连续的假象是怎么实现的.
所谓的中控器实际上就是一个指针数组(即数组元素是指针),叫map(注意不是STL的map容器)
上面讲的每一段小的连续子空间叫deque的缓冲区
然后map数组的每一个元素,即每一个指针都会指向一个相应的缓冲区,
当map数组满了以后,需要再找一个更大的空间来作为map,如下图
中控器对这些一段一段的缓冲区有一个很好的组织之后,下面就是迭代器发挥作用了.
一个deque会有两个迭代器,start和finish
start 迭代器负责起始的那块缓冲区,finish迭代器负责最后的那块缓冲区
每个迭代器会有四个指针域cur first last node
node指向在map中该缓存区所处的位置
first指向当前缓冲区的整体空间的头部
last指向当前缓冲区的整体空间的尾部
对于finish迭代器,cur指向当前缓冲区已用空间的最后一个元素位置(的下一个位置),
对于start迭代器,cur指向当前缓冲区已用空间的第一个元素