std::deque ( double-ended queue ,双端队列)是可以进行下标访问的顺序容器,它允许在其首尾两端快速插入及删除元素。
在 deque 任一端插入或删除元素不会让当前正在使用的迭代器失效
deque 上常见操作的复杂度(效率)如下:
随机访问——常数 O(1)
在结尾或起始插入或移除元素——常数 O(1)
插入或移除元素——线性 O(n)
与 std::vector 相反, deque 的元素不一定是相邻存储的,其结构有点类似于散列表,有许多顺序结构的缓冲区(buffer)来存储元素,这些缓冲区存储在内存的任意位置,由一个“中控台”负责将这些缓冲区联系起来管理。
"中控台"是一个使用vector结构的数组,里边存储的是指向各个缓冲区(buffer)的指针。当"中控台"的指针数量过多的时候,就会进行扩充,也就是在内存中寻找一块两倍大小的缓冲区,将之前的指针全部拷贝过来。
值得一提的是,由于Deque的左右两边都会扩展,所以插入"中控台"的指针元素会从中间开始往两边扩展,而不是从最左边开始扩展。
以下是Deque的头文件
这里的BufSize是指每一段缓冲区的大小,这个大小可以人为指定。如果不指定,则使用预设值,具体如下:
每个Deque都会包含如下数据类型,其中迭代器类型的start和finish分别指向Deque的头和尾。指针类型的map指向"中控台"的开始位置。size_type类类型的 map_size表示当前"中控台"的大小。
Deque类型的迭代器中共有4个指针,故一个迭代器占16个字节。
因此一个Deque占2*16+4+4=40个字节。(32位计算机)
Deque迭代器图示如下:
头文件部分:
其中,指针cur指向的是当前所指向的元素。first和last分别指向当前缓冲区的开头和结尾处。node则指向"中控台"。
插入方法insert源码:
在元素的中间插入时,会进行元素的搬移,此时Deque会比较往前和往后搬移元素的开销,然后选择开销相对小的方向进行搬移。(但这样也会耗费很长的时间)
其他方法的源码
先写这么多吧,这些笔记主要是自己记录,以便查看。如有错误,欢迎指正。
附:各种容器的size: