栈和队列是每个程序员都熟悉的抽象数据类型,但在 STL 中它们被设计成容器适配器——不是真正的容器,而是包装了其他底层容器,只暴露有限的接口。这种'适配器'模式的好处是,你可以轻松换用不同的底层实现(比如用 vector 或 list)而不修改上层代码。
stack、queue 的接口
stack 和 queue 的接口非常精简,你基本一用就会:
stack
push(val):压入栈顶pop():弹出栈顶元素top():返回栈顶引用empty()、size():判空和大小
queue
push(val):队尾入队pop():队头出队front()、back():队头、队尾引用empty()、size():同上
这些操作的时间复杂度都是 O(1),但具体行为取决于底层容器。STL 默认选用了 deque(双端队列),因为它兼顾了头尾操作的高效和随机访问的假象。
为什么是 deque?
deque 内部由多个连续内存块拼接而成,通过一个复杂的迭代器来维护'逻辑连续'的假象。它支持在头尾 O(1) 插入删除,又不像 vector 那样需要搬运元素。stack 只需访问一端,queue 两端都要用,所以 deque 是自然的选择。
deque 迭代器的实现堪称模板元编程的典范,下面是从 STL 源码中抽出的简化版,值得花时间读一读:
#pragma once
#include <vector>
#include <list>
#include <deque>
using namespace std;
namespace wgm {
template<class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator {
typedef __deque_iterator<T, T&, T*, BufSiz> iterator;
__deque_iterator<T, T&, T*, BufSiz> const_iterator;
T value_type;
Ptr pointer;
Ref reference;
T** map_pointer;
difference_type;
__deque_iterator self;
__deque_iterator(T* x, map_pointer y) : (x), (*y), (*(y + ())), (y) {}
__deque_iterator() : (), (), (), () {}
__deque_iterator( iterator& x) : (x.cur), (x.first), (x.last), (x.node) {}
{ node = new_node; first = *new_node; last = first + (()); }
reference *() { *cur; }
pointer ->() { &(*()); }
self& ++() {
++cur;
(cur == last) { (node + ); cur = first; }
*;
}
self ++() {
self tmp = *;
++*;
tmp;
}
self& --() {
(cur == first) { (node - ); cur = last; }
--cur;
*;
}
self --() {
self tmp = *;
--*;
tmp;
}
self& +=(difference_type n) {
difference_type offset = n + (cur - first);
(offset >= && offset < (())) cur += n;
{
difference_type node_offset = offset > ? offset / (()) : -((-offset - ) / ()) - ;
(node + node_offset); cur = first + (offset - node_offset * (()));
}
*;
}
self +(difference_type n) {
self tmp = *;
tmp += n;
}
self& -=(difference_type n) { * += -n; }
self -(difference_type n) {
self tmp = *;
tmp -= n;
}
reference [](difference_type n) { *(* + n); }
==( self& x) { cur == x.cur; }
!=( self& x) { !(* == x); }
<( self& x) { (node == x.node) ? (cur < x.cur) : (node < x.node); }
:
T* cur;
T* first;
T* last;
map_pointer node;
};
}


