vector VS deque
- vector是单向开口的连续线性空间,deque则是一种双向开口的连续线性空间。
- 所谓双向开口,指的是可以在头尾两端做元素的插入和删除操作
- vector虽然技术上可以做到双向开口,但是在头部操作的效率非常差,无法被接受
-
deque和vector的最大差异:
- 一是:在于deque允许常数级别对头部插入或者删除
- 二是:deque没有所谓容量(capacity)观念
- 因为deque是动态的以分段连续空间组合而成,随时可以增加一段新的空间并连接起来。而vector是”旧空间不足就申请一个更大的空间,然后复制元素,再释放旧空间“。
- 也因此,deque没有必要提供所谓的空间保留(reserve)功能
-
虽然deque也提供随机存取迭代器,但是它的迭代器并不是普通指针,其复杂度比vector高太多了,这也影响了各个运算层面。所以,除非必要,我们应该尽可能的选择vector而不是deque
#include <iostream>
#include <list>
#include <vector>
#include <queue>
std::ostream& operator<<(std::ostream& ostr, const std::list<int>& list)
{
for (auto &i : list) {
ostr << " " << i;
}
return ostr;
}
int main()
{
std::queue<int> myqueue;
myqueue.push(12);
myqueue.push(20);
myqueue.push(75);
printf("myqueue.back: %d, myqueue.front: %d\n", myqueue.back(), myqueue.front());
std::vector<int> myvector;
myvector.push_back(12);
myvector.push_back(20);
myvector.push_back(75);
printf("myvector.back: %d, myvector.front: %d\n", *(--myvector.end()), *myvector.begin());
}
deque的中控器
deque是连续空间(逻辑上),C++中连续线性空间有array和vector。
- array无法成长
- vector虽然可以成长,但是只能向尾端成长,而且其所谓成长其实是个假象。
- 事实上是(1)另找一个更大空间(2)将原数据复制过去(3)释放原空间三部曲。
- 如果不是vector每次配置新空间都会留下一些余地,那么代价会非常高
- deque是有一段一段的定量连续空间构成
- 一旦有必要再deque的前端或尾端增加空间,就配置一段定量连续空间,串接再整个deque的头部或者尾部
- deque的最大任务,就是在这些分段的定量连续空间上,维护其整体连续的假象,并提供随机存取的接口,避开”重新申请、复制、释放“的三部曲,代价是复杂的迭代器架构。
deque为了维持这个整体连续的假象,设置了一个中控器作为主控。
- 这个所谓的主控可以看成是一个map(注意不是STL中的map)
- 这个map是一小块连续空间,其中每个元素节点(node)都是指针,指向另一端较大的连续线性空间,称为缓冲区。
- 缓冲区才是deque的存储空间主体。
- STL允许我们指定缓冲区大小,默认值0表示将使用512bytes缓冲区
- 把各种令人头皮发麻的型别定义(为了型别安全,这是必要的)整理一下,我们可以发现,map其实是一个
T**
。也就是说它是一个指针,所指之物又是一个指针,指向类型为T的一块空间
deque的迭代器
deque是分段连续空间,维持其”整体连续“假象的任务,落在了迭代器的operator++
和operator--
两个运算子身上。
一个deque迭代器应该满足如下条件:
- 首先,它必须能够指出分段连续空间(也就是缓冲区)在哪里
- 其次,它必须能够判断自己是否已经处于其所在缓冲区的边缘
- 如果是,一旦前进或者后退就必须跳到下一个或者上一个缓冲区。
- 为了正确跳跃,deque必须随时掌握掌控中心map