1.deque不是完全的线性空间,而是一段一段的定量线性空间,被称为缓冲区,缓冲区里存放数据。deque还有一个指针数组 map,map中存放指针用来指向缓冲区。map有管控中心的作用
2.deque尽量让map数组中间的元素指向缓冲区,两边的元素备用。
3.deque的迭代器也是Random Acess Iterators类型。由于各个缓冲区不是相邻的,所以像是++
和--
这种操作有可能跨缓冲区。所以deque的迭代器需要存一个指向管控中心的指针node,node指向map数组中索引这片缓冲区的那个指针。这样它就能跨缓冲区了。
4.deque的迭代器里有四个数据成员,是4个指针,一个是上面说的node,还有的是指向当前元素的指针cur,指向当前元素所在缓冲区的头的指针first,指向当前元素所在缓冲区的尾的指针last。last前面可能有一部分空间还没有被分配数据,属于备用区。
5.deque除了维护一个指向map的指针外,还有两个迭代器start和finish,分别指向第一个缓冲区的第一个元素和最后一个缓冲区的最后一个元素的下一个位置(因为迭代器的前闭后开要求)
6.对于push_front,当start已经指向第一个缓冲区的左边界了,需要在前面配置一个新的缓冲区;对于push_back,当finish指向最后一个缓冲区的最后一个位置(finish.first + buff_size - 1
),需要在后面配置一个新的缓冲区。同样对于pop_front,如果start指向第一个缓冲区的最后一个位置,在析构这个元素递增start后,还要释放这个已经没有元素的缓冲区;对于pop_back,如果finish指向最后一个缓冲区的左边界,那么同样也需要释放这个缓冲区。
7.随着push_back和push_front或者insert等操作,map中元素越来越多。当map不能保证头和尾都有一个位置备用的时候,就需要重整map数组。有时候,map数组是足够大小的,但元素偏向了头或者偏向了尾,这时候只需要调整下元素位置,集体在map中往前或者往后挪动就可以。而有时候,新开辟的缓冲区太多了,map已经放不下指针来指向新的缓冲区了,这时候就不得不重新开辟一片更大的内存作为新的map数组,把旧的map中的元素都拷贝的新的map中去,并且把旧的map析构、释放。
8.对于insert,如果插入位置前面的元素比较少,那么就把前面的元素往前挪,否则就把插入位置后面的元素往后挪动。同样,对于erase,如果插入位置前面的元素比较少,就把前面的元素往后挪动,否则就把后面的元素往前挪动。