STL源码剖析学习六:deque
deque是一种双向开口的连续性线性空间,可以在头尾都进行元素的插入和删除操作。
是动态地以分段连续的空间组合而成,随时可以增加一段新的空间并连接起来。因此没有容量和空间保留的概念。
提供随机访问迭代器,但不是以指针实现,复杂度很大。因此要多用vector少用deque
对deque的排序操作,为了提高效率,可将deque先复制到vector中,排序后再拷回来。
deque的中控器:
从逻辑上看deque是连续空间,但是可以任意增长。有必要时在deque的前端或者尾端增加新的空间,便配置一段定量连续空间,串接在整个deque上。deque的最大任务就是维护其整体连续的假象,并提供随机访问接口。
用一段map作为主控,是一小段连续的空间,每一个元素时一个node,都是指针,指向另一段较大的线性连续的空间,称为缓冲区。
map实际是一个T**,是一个指针,所指之物是另一个指针。
deque的迭代器:
必须能指出分段连续空间在哪里。
必须能分辨出自己是否已经在缓冲区的边缘
如果是,需要前进或者后退时就要找到上一个/下一个缓冲区。
为了能实现跳跃,deque必须随时掌握管控中心
void set_node(map_pointer new_node) { node = new_node; first = *new_node; last = first + difference_type(buffer_size()); }
deque的数据结构:
除了维护一个先前说过的指向map的指针外,也维护start finish两个迭代器,指向第一缓冲区的第一个元素和最后缓冲区的最后一个元素的下一位置。
当前map的大小,如果大小不够就需要另外配置一个新的map
deque的构造与内存管理:
create_map_and_nodes()负责产生并安排好deque的结构
{
需要的节点数=(元素个数/每个缓冲区能容纳的元素个数)+1
如果刚好整除 会多配一个节点
一个map要管理最少8个最多为“所需节点数+2”个node
使nstart nfinish指针指向map的中间,使前后能扩充的范围一样大,每个节点对应一个缓冲区
为每个节点配置缓冲区
把start和finish指向对应的缓冲区中的位置
}
pop_back时,若该缓冲区中已经没有其他元素,就要把该缓冲区释放掉
判断是否可以释放该缓冲区
在pop_back_aux()中释放该缓冲区
{
析构元素
释放缓冲区
调整finish的状态,指向之前一个node的最后一个元素
}
当push_back时若某缓冲区尾部没有足够的空间可用,就先配置一块新的缓冲区,再设置元素
当map不够大时,就需要重新整治,由reserve_map_at_back()进行判断,实际操作由reallocate_map()进行。
配置新的map时需要配置个更大的区域存放map,拷贝原来的map,配置新的map,释放原来的map
和vector的重新配置类似
deque的元素操作:
erase()删除某个元素
{
判断需要删除的pos是离头比较近还是离尾部比较近
如果是头部比较近就把从头部到pos那部分copy_backward到pos+1开始的位置(从后往前拷贝)
然后pop_front()
如果离尾部比较近也同理
}
insert()把某元素插入到某位置
{
和erase类似,判断pos离头比较近还是尾比较近。
如果到头部比较近,则先push_front插入一个元素,然后把从第二位到pos位置的元素都拷贝到从第一位开始的地方。然后把pos位置赋值为新的值。
离尾部比较近同理
}