Deque
Deque为双端队列,提供双端进出的操作,特点如下:
- 包含一个map链表,用来将存放元素的多个缓冲区“连接”起来,使用者使用时像是拥有了连续空间。
- 包含start、finish两个迭代器和一个pointer指针
Deque的实现:
Deque的iterator
deque迭代器的设计比较精巧,包含node、first、last、cur四个指针。特定如下:
- 若_Duque_iterator中node指向某个缓冲区,first指向buffer开端,last指向buffer末端,cur指向buffer存元素的位置。
- 对于start迭代器,其cur指向buffer存元素的开头;对于end迭代器,其cur指向buffer存元素的末尾。
- 用于遍历的iterator的cur指向buffer中的当前访问元素,当iterator走到buffer边界时,要有能力跳到下一个buffer,通过map中的node实现。
insert操作
开头插入调用push_front();末尾调用push_back();中间调用insert_aux();
insert操作会计算插入位置position到首尾的距离,在尽量减少元素移动的情况下加入。
deque操作符的重载
- 操作符 [ ]
reference operator[](size_type n){
return start[difference_type(n)];
}
- 操作符 *
reference operator*() const{
return *cur;
}
- 操作符 ->
pointer operator->() const{
return &(operator*());
}
- 操作符 - 两对象之间的相减,a - b获得从b到a的长度。
difference_type operator-(const self& x) const{
return difference_type(buffer_size()) * (node - x.node - 1) +
(cur - first) + (x.last - x.cur);
// 其中 (node - x.node - 1) 计算两根迭代器之间完整buffer的长度
// (cur - first) 计算末尾buffer的元素量
// (x.last - x.cur) 计算起始buffer的元素量
- 操作符++、--
self& operator++(){ // 前置++
++cur; // 切换至下一元素
if (cur == last){ // 如果抵达缓冲区尾部
set_node(node + 1); // 跳至下一个节点
cur = first; // 的起点
}
return *this;
}
self operator++(int){ // 后置++
self tmp = *this;
++*this;
return tmp; //返回当前值,但是指针已经后移
}
self& operator--(){
if (cur == first){ // 先判断当前是否在缓冲区起点
set_nde(node - 1);
cur = last;
}
--cur;
return *this;
}
self operator--(int){
self *tmp = *this;
--*this;
return tmp;
}
// 用于跳转节点的代码
void set_node(map_pointer new_node){
node = new_node;
first = *new_node;
last = first + difference_type(buffer_size());
value_type和difference_type之间的加减
- 操作符 +和+= 用作value_type和difference_type之间的相加。
操作符+实际调用操作符+=,+=设计时要考虑到节点可能跳过多个缓冲区。
- 操作符 -和-= 用作value_type和difference_type之间的相减。
操作符-实际调用操作符-=,操作符-=可调用操作符+=。 - 操作符[]
对象后接取址符[difference_type n],也可以用作元素的跳转。
使用容器Deque实现queue和stack
相当于一种适配器模式。
- stack和queue都允许遍历
- stack和queue都可以选择list或者deque作为底层结构
reference
- 侯捷《STL源码剖析》
更多精彩文章,欢迎关注公众号“Li的白日呓语”。