参考文献:
《STL源码剖析》
...........................................................................................................................................................
一. deque 概述
vector是单向开口的连续性线性空间,deque则是一种双开的连续性空间,即两边都可以进行插入和删除操作(vector也可进行头部的删除、插入操作,但效率很差,不被接受)。
下图为deque示意图:
deque和vector最大差异,一是deque允许在常数时间内对头部元素进行插入和移除操作,二在于deque没有所谓的容量的概念,因为它是动态地以分段连续空间组合而成,随时可以增加一段新的空间并链接起来。
虽然deque也提供Random Access Iterator,但它的迭代器并不是普通指针,其复杂度远高于vector,所以除非必要尽可 能使用vector。为了deque排序效率最高,deuqe会先将所有的元素复制到vector中,进行排序后,再复制回deque
二. deque 的中控器
deque是一段一段连续的空间构成,一旦在deque前端或尾端增加新空间,便配置一段定量连续空间,串联在头端和尾端。deque的最大任务就是将这些定量的空间,维护成连续的假象,并提供随机存储的接口,避开了“重新配置、复制、释放”的轮回,代价即是复杂的迭代器架构。
既然是分段连续的线性空间,就必须要有中央控制,而为了维持连续的假象,数据结构的设计及迭代器前进后退等操作都比较麻烦,所以deque的实现代码分量远比vector或list都多得多。
deque采用一块map(不是STL的map容器)作为主控,这里的map是一块连续空间,其中每个元素都是指针,指向另一段连续线性空间,称为缓冲区。缓冲区才是deque的存储空间主体。
1 template <class T,class Alloc=alloc,size_t BufSiz=0> 2 class deque{ 3 public: 4 typedef T value_type; 5 typedef value_type* pointer; 6 ... 7 protected: 8 typedef pointer* map_pointer; 9 protected: 10 map_pointer map; //指向map,map是连续空间,其内的每个元素都是一个指针,指向一块缓冲区 11 size_type map_size; //map可容纳多少指针 12 ... 13 };
从上面可以看出,map其实是一个T**,也就是说它是一个指针,所指向另一个指针,指向型别为T的一块空间。具体如下图:
三. deque 使用实例(理解)
1 #include <deque> 2 #include <iostream> 3 #include <algorithm> 4 #include <stdexcept> 5 using namespace std; 6 7 void print(int num) 8 { 9 10 cout << num << " "; 11 } 12 13 int main() 14 { 15 //1. 初始化 16 deque<int> v; 17 deque<int>::iterator iv; 18 19 v.assign(10, 2);//将10个值为2的元素赋到deque中 20 cout << v.size() << endl; //返回deque实际含有的元素数量 21 cout << endl; 22 23 //2. 添加 24 v.push_front(666); 25 for (int i = 0; i < 10; i++) 26 v.push_back(i); 27 for_each(v.begin(), v.end(), print);//需要#include <algorithm> 28 cout << endl; 29 cout << v.size() << endl; 30 cout << endl; 31 32 33 34 //3. 插入及遍历、逆遍历 35 v.insert(v.begin() + 3, 99); 36 v.insert(v.end() - 3, 99); 37 for_each(v.begin(), v.end(), print); 38 cout << endl; 39 for_each(v.rbegin(), v.rend(), print);//在逆序迭代器上做++运算将指向容器中的前一个元素 40 cout << endl; 41 42 //一般遍历写法 43 for(iv = v.begin(); iv != v.end(); ++iv) 44 cout << *iv << " "; 45 cout << endl; 46 cout << endl; 47 48 //4. 删除 49 v.erase(v.begin() + 3); 50 51 for_each(v.begin(), v.end(), print); 52 cout << endl; 53 v.insert(v.begin() + 3, 99);//还原 54 55 v.erase(v.begin(), v.begin() + 3); //注意删除了3个元素而不是4个 56 for_each(v.begin(), v.end(), print); 57 cout << endl; 58 59 v.pop_front(); 60 v.pop_back(); 61 for_each(v.begin(), v.end(), print); 62 cout << endl; 63 cout << endl; 64 65 66 67 //5. 查询 68 cout << v.front() << endl; 69 cout << v.back() << endl; 70 71 //危险的做法,但一般我们就像访问数组那样操作就行 72 //for (int i = 15; i < 25; i++) 73 //cout << "Element " << i << " is " << v[i] << endl; 74 //安全的做法 75 int i; 76 try 77 { 78 for (i = 15; i < 25; i++) 79 cout << "Element " << i << " is " << v.at(i) << endl; 80 } 81 catch (out_of_range err)//#include <stdexcept> 82 { 83 cout << "out_of_range at " << i << endl; 84 } 85 cout << endl; 86 87 //6. 清空 88 v.clear(); 89 cout << v.size() << endl;//0 90 for_each(v.begin(), v.end(), print); //已经clear,v.begin()==v.end(),不会有任何结果。 91 92 return 0; 93 }