Deque
std::deque(双端队列)时一种支持索引的序列容器,在双端允许快速插入和删除。另外,在双端的插入和删除不会使剩余元素的指针和引用非法。
相较于std::vector,deque的元素不是连续存储的:典型的实现使用单独分配的固定大小的数组序列,用额外的记录记录数组单元的序列。这意味着deque的索引访问必须执行两次指针解引用。
deque 的存储空间会自动依据需求去拓展和收缩。deque的拓展较vector更加的cheaper,因为不会将存在的元素进行拷贝到一个新的存储空间。另一方面,deque通常有很大的最小内存成本;仅有一个元素的deque对象需要分配整个内在数组。
deque上的常规操作的复杂度(效率)如下:
- 随机访问-constant O(1)
- 首位插入和删除-constant O(1)
- 元素的插入和删除-线性 O(n)
std::deque 满足 Container, AllocatorAwareContainer, SequeuceContainer 和 ReversibleContainer
指导思想
典型实现用单独分配的固定大小数组的序列。
关于buffer
inline size_t __deque_buf_size(size_t __size) {
return __size < 512 ? size_t(512 / __size) : size_t(1);
}
- 固定大小(512字节)的buffer能容纳的最大目标类型数量。
- buffer即为典型实现用单独分配的固定大小数组。
迭代器
- 迭代器类型为随机访问迭代器,实现
[n]
、+n
template <class _Tp, class _Ref, class _Ptr>
struct _Deque_iterator {
typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator;
typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); }
typedef random_access_iterator_tag iterator_category;
typedef _Tp value_type;
typedef _Ptr pointer;
typedef _Ref reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef _Tp** _Map_pointer;
typedef _Deque_iterator _Self;
_Tp* _M_cur; // 当前指向的元素
_Tp* _M_first; // 本数组的第一个元素
_Tp* _M_last; // 本数组的最后一个元素
_Map_point _M_node; // 代表本数组在双端队列中的结点
_Deque_iterator(_Tp* __x, _Map_pointer __y)
: _M_cur(__x), _M_first(*__y), _M_last(*__y + _S_buffer_size()), _M_node(__y) {}
——Deque_iterator() :_M_cur(0), _M_cur(0), _M_frist(0), _M_last(0). _M_node(0) {}
_Deque_iterator(const iterator& __x)
: _M_cur(__x._M_cur),_M_first(__x._M_first), _M_last(__x._M_last), _M_node(__x._M_node) {}
}
reference operator* const {return *_M_cur; }
pointer operator->() const { return _M_cur; }
difference_type operator-(const Self& __x) const {
return difference_type(S_buffer_size()) * (_M_node - _x._M_node - 1) +
(_M_cur - _M_first) + (__x._M_last - __x.M_cur);
}
_Self& operator++() {
++_M_cur;
if(_M_cur == _M_last) {
_M_set_node(_M_node + 1);
_M_cur = _M_first;
}
return *this;
}
_Self operator++(int) {
_Self __tmp = *this;
++*this;
return __tmp;
}
_Self& operator--() {
if(_M_cur == _M_start) {
_M_set_node(_M_node -1)
_M_cur = _M_last;
}
--_M_cur;
return *this;
}
_Self operator--(int) {
_Self __tmp = *this;
--*this;
return __tmp;
}
_Self& operator+=(difference_type __n) {
difference_type __offset = __n + (_M_cur - _M_first);
if(__offset >= 0 && __offset < diffence_type(_S_buffer_size()))
_N_cur += __n;
else
difference_type __node_offset =
__offset > 0 ? __offset / difference_type(_S_buffer_size())
: -difference_type((-__offset - 1) / _S_buffer_size())-1;
_M_set_node(_M_node + __node_offset);
_M_cur = _M_first +
(__offset - __node_offset * difference_type(_S_buffer_size()));
}
return *this;
}
}
分配器
template <class _Tp, class _Alloc, bool __is_static>
class _Deque_alloc_base {
public:
typedef typename _Alloc_traits<_Tp, _Alloc>::allocator_type allocator_type;
// 节点分配器处理的类型为_Tp
allocator_type get_allocator() const { return _M_node_allocator; }
_Deque_alloc_base(const allocator_type& __a)
: _M_node_allocator(__a), _M_map_allocator(__a), _M_map(0), _M_map_size(0) {
}
protected:
typedef typename _Alloc_traits<_Tp*, _Alloc>::allocator_type _Map_allocator_type;
// 映射分配器处理的类型为_Tp*
allocator_type _M_node_allocator;
_Map_allocator_type _M_map_allocator;
// 分配__deque_buf_size(sizeof(_Tp))个Tp的内存, 并返回起始地址
_Tp* _M_allocate_node() {
return _M_node_allocator.allocate(__deque_buf_size(sizeof(_Tp)));
}
// 释放__deque_buf_size(sizeof(_Tp))个Tp的内存, 起始地址为__p
void _M_deallocate_node(_Tp* __p) {
_M_node_allocator.dellocate(__p, __deque_buf_size(sizeof(_Tp)))
}
// 分配n个字节的内存空间以存储_Tp*,返回起始地址_Tp**
_Tp** _M_allocate_map(size_t __n) {
return _M_map_allocator.allocate(__n);
}
// 释放n个Tp*的内存, 起始地址为__p
void _M_deallocate_map(_Tp** __p, size_t __n) {
_M_map_allocator.deallocate(__p, __n);
}
_Tp** _M_map; // 映射表起始地址
size_t _M_map_size; // 映射表大小
};
静态版本,使用静态函数实现内存分配和回收。
template <class _Tp, class _Alloc>
class _Deque_alloc_base<_Tp, _Alloc, true> {
public:
typedef typename _Alloc_traits<_Tp, _Alloc>::allocator_type allocator_type;
allocator_type get_allocator() const { return allocator_type(); }
_Deque_alloc_base(const allocator_type&) : _M_map(0), _M_map_size(0) {}
protected:
typedef typename _Alloc_traits<_Tp, _Alloc>::_Alloc_type _Node_alloc_type;
typedef typename _Alloc_traits<_Tp*, _Alloc>::_Alloc_type _Map_alloc_type;
// 分配__deque_buf_size(sizeof(_Tp))个Tp的内存, 并返回起始地址
_Tp* _M_allocate_node() {
return _Node_alloc_type::allocate(__deque_buf_size(sizeof(_Tp)));
}
// 释放__deque_buf_size(sizeof(_Tp))个Tp的内存, 起始地址为__p
void _M_deallocate_node(_Tp* __p) {
_Node_alloc_type::dellocate(__p, __deque_buf_size(sizeof(_Tp)))
}
// 分配n个字节的内存空间以存储_Tp*,返回起始地址_Tp**
_Tp** _M_allocate_map(size_t __n) {
return _Map_alloc_type::allocate(__n);
}
// 释放n个Tp*的内存, 起始地址为__p
void _M_deallocate_map(_Tp** __p, size_t __n) {
_Map_alloc_type::deallocate(__p, __n);
}
}
Deque
template <class _Tp, class _Alloc>
class _Deque_base : public _Deque_alloc_base<_Tp, _Alloc,
_Alloc_traits<_Tp, _Alloc>::_S_instanceless> {
public:
typedef _Deque_alloc_base<_Tp, _Alloc,
_Alloc_traits<_Tp, _Alloc>::_S_instanceless>
_Base;
typedef typename _Base::allocator_type allocator_type;
typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator;
typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator;
_Deque_base(const allocator_type& __a, size_t __num_elements)
: _Base(__a), _M_start(), _M_finish() {
_M_initialize_map(__num_elements);
}
_Deque_base(const allocator_type& __a) : _Base(__a), _M_start(), _M_finish() {
}
~_Deque_base();
protected:
void _M_initialize_map(size_t);
void _M_create_nodes(_Tp** __nstart, _Tp** __nfinish);
void _M_destroy_nodes(_Tp** __nstart, _Tp** __nfinish);
enum { _S_initial_map_size = 8 };
protected:
iterator _M_start;
iterator _M_finish;
}
定义
template class<class _Tp, class _Alloc>
_Deque_base<_Tp, _Alloc>::~Deque_base() {
if(_M_map) {
// 释放所有迭代器指向的节点(buffer)
_M_destroy_nodes(_M_start._M_node, _M_finish._M_node + 1);
// 释放映射表所占据的连续内存(数组)
_M_deallocate_map(_M_map, _M_map_size);
}
}
template<class _Tp, class _Alloc>
void _Deque_base<_Tp, _Alloc>::_M_initialize_map(size_t __num_elements) {
size_t __num_nodes =
__num_elements / __deque_buf_size(sizeof(_Tp)) + 1;
_M_map_size = max((size_t)_S_initial_map_size, __num_nodes + 2);
_M_map = _M_allocate_map(_M_map_size);
// 映射首尾至少各留出一个节点指针用于未来的增长,没有分配元素
_Tp** _nstart = _M_map + (_M_map + (_M_map_size - __num_nodes))/2
_Tp** __nfinish = __nstart + __num_nodes;
__STL_TRY {
_M_create_nodes(__nstart, __nfinish);
}
__STL_UNWIND((_M_Deallocate_map(_M_map, _M_map_size),
_M_map = 0, _M_mmap_size = 0));
// 迭代器绑定节点
_M_start._M_set_node(__nstart);
_M_finish._M_set_node(_nfinish-1);
_M_start._M_cur = _M_start._M_first;
_M_finish._M_cur = _M_finish._M_first + __num_elements
% __deque_buf_size(sizeof(_Tp));
}
template <class _Tp, class _Alloc>
void _Deque_base<_Tp,_Alloc>::_M_create_nodes(_Tp** __nstart, _Tp** __nfinish)
{
_Tp** __cur;
__STL_TRY {
for (__cur = __nstart; __cur < __nfinish; ++__cur)
*__cur = _M_allocate_node();
}
__STL_UNWIND(_M_destroy_nodes(__nstart, __cur));
}
template <class _Tp, class _Alloc>
void _Deque_base<_Tp, _Alloc>::_M_destory_nodes(_Tp** __nstart, _Tp** __nfinish) {
for(_Tp** __n = __nstart; __n < __nfinish; ++__n) {
_M_deallocate_node(*__n);
}
}
template <class _Tp, class _Alloc>
class deque : protected _Deque_base<_Tp, _Alloc> {
typedef _Deque_base<_Tp, _Alloc> _Base;
public:
typedef _Tp value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef typename _Base::allocator_type allocator_type;
allocator_type get_allocator() const { return _Base::get_allocator(); }
public:
typedef typename _Base::iterator iterator;
typedef typename _Base::const_iterator const_iterator;
#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
typedef reverse_iterator<const_iterator> const_reverse_iterator;
typedef reverse_iterator<iterator> reverse_iterator;
#else
typedef reverse_iterator<const_iterator, value_type,
const_reference, difference_type>
const_reverse_iterator;
typedef reverse_iterator<iterator, value_type,
reference, difference_type>
reverse_iterator;
#endif
protected:
typedef pointer* _Map_pointer; // value_type**
static size_t _S_buffer_size() { return __deque_buf_size(sizeof(_Tp)); } // 一个buffer(节点)能存储多少个对象(元素)。
protected:
#ifdef __STL_USE_NAMESPACES
using _Base::_M_initialize_map; // 初始化Map需要的内存,为Map元素添加指向的节点
using _Base::_M_create_nodes; // 为范围内节点分配内存
using _Base::_M_destroy_nodes; // 释放范围内节点内存
using _Base::_M_allocate_node; // 为单个节点分配内存
using _Base::_M_deallocate_node; // 为单个节点释放内存
using _Base::_M_allocate_map; // 为Map分配内存
using _Base::_M_deallocate_map; // 释放Map内存
using _Base::_M_map;
using _Base::_M_map_size;
using _Base::_M_start;
using _Base::_M_finish;
#endif
public:
iterator begin() { return _M_start; }
iterator end() { return _M_finish; }
const_iterator begin() const { return _M_start; }
const_iterator end() const { return _M_finish; }
reverse_iterator rbegin() { return reverse_iterator(_M_finish); }
reverse_iterator rend() { return reverse_iterator(_M_start); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(_M_finish); }
const_reverse_iterator rend() const { return const_reverse_iterator(_M_start); }
reference operator[](size_type __n)
{ return _M_start[difference_type(__n)]; }
const_reference operator[](size_type __n) const
{ return _M_start[difference_type(__n)]; }
#ifdef __STL_THROW_RANGE_ERRORS
void _M_range_check(size_type __n) const {
if(__n >= this->size())
__stl_throw_range_error("deque");
}
reference at(size_type __n)
{ _M_range_check(__n); return (*this)[__n]; }
const_reference at(size_type __n) const
{ _M_range_check(__n); return (*this)[__n]; }
#endif
reference front() { return *_M_start; }
reference back() {
iterator __tmp = _M_finish;
--__tmp;
return *__tmp;
}
size_type size() const { return _M_finish - _M_start; }
size_type max_size() const { return size_type(-1); }
bool empty() const { return _M_finish == _M_start; }
public:
explicit deque(const allocator_type& __a = allocator_type())
: _Base(__a, 0) {}
deque(const deque& __x) : _Base(_x.get_allocator(), __x.size()) {
uninitialized_copy(__x.begin(), __x.end(), _M_start);
}
deque(size_type __n, const value_type& __value,
const allocator_type& __a = allocator_type()) : _Base(__a, __n)
{ _M_fill_initialize(__value); }
explicit deque(size_type __n) : _Base(allocator_type(), __n) {
_M_fill_initialize(value_type());
}
#ifdef __STL_MEMBER_TEMPLATES
template <class _InputIterator>
deque(_InputIterator __first, _InputIterator __last,
const allocator_type& __a = allocator_type()) : Base(__a) {
typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
_M_initialize_dispatch(__first, __last, _Integral());
}
template <class _Integer>
void _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) {
_M_initialize_map(__n);
_M_fill_initialize(__x);
}
template <class _InputIter>
void _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, __false_type) { _M_range_initialize(__first, __last, __ITERATOR_CATEGORY(__first)); }
#else
deque(const value_type* __first, const value_type* __last,
const allocator_type& __a = allocator_type())
: _Base(__a, __last - __first) {
uninitialize_copy(__first, __last, _M_start);
}
deque(const_iterator __first, const_iterator __last,
const allocator_type& __a = allocator_type())
: _Base(__a, __last - __first)
{ uninitialized_copy(__first, __last, _M_start); }
#endif
~deque() { destory(_M_start, _M_finish); } // 存储元素主动调用析构函数
deque& operator=(const deque& __x) {
const size_type __len = size();
if(&__x != this) {
if(_len >= __x.size())
erase(copy(__x.begin(), __x.end(), _M_start), _M_finish);
else {
const_iterator __mid = __x.begin() + difference_type(__len);
copy(__x.begin(). __mid, _M_start);
insert(_M_finish, __mid, __x.end());
}
}
return *this;
}
void swap(deque& __x) {
__STD::swap(_M_start, __x._M_start);
__STD::swap(_M_finish, __x._M_finish);
__STD::swap(_M_map, __x._M_map);
__STD::swap(_M_map_size, __x._M_map_size);
}
}
public:
void assign(size_type __n, const _Tp& __val) {
_M_fill_assign(__n, __val);
}
void _M_fill_assign(size_tyoe __n, const _Tp& __val) {
if(__n > size()) {
fill(begin(), end(), __val);
insert(end(), __n - size(), __val);
}
else {
erase(begin() + n, end());
fill(begin(), end(), __val);
}
}
push_back
public:
// _M_finish._M_last 本buffer结束标记,不能赋值。
void push_back(const value_type& __t) {
if(_M_finish._M_cur != _M_finish._M_last - 1) {
construct(_M_finish._M_cur, __t);
++_M_finish._M_cur;
}
else
_M_push_back_aux(__t);
}
void _M_push_back_aux(const value_type& __t) {
value_type __t_copy = __t;
_M_reserve_map_at_back();
*(_M_finish._M_node + 1) = _M_allocate_node(); // 分配尾部新节点
_STL_TRY {
// 将原来的超尾迭代器,重新构造赋值
construct(_M_finish._M_cur, __t_copy);
// 重设超尾迭代器关联节点和指向超尾元素
_M_finish._M_set_node(_M_finish._M_node + 1);
_M_finish._M_cur = _M_finish._M_first;
}
__STL_UNWIND(_M_deallocate_node(*(_M_finish._M_node + 1)));
}
void _M_reserve_map_at_back(size_type __nodes_to_add = 1) {
if(__nodes_to_add + 1 > _M_map_size - (_M_finish._M_node - _M_map)) {
_M_reallocate_map(__nodes_to_add, false);
}
}
void _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front) {
size_type __old_num_nodes = _M_finish._M_node - _M_start._M_node + 1;
size_type __new_num_nodes = __old_num_nodes + __nodes_to_add;
_Map_pointer __new_nstart;
if(_M_map_size > 2*__new_num_nodes) {
__new_nstart = _M_map + (_M_map_size - __new_num_nodes) / 2
+ (__add_at_front ? __nodes_to_add : 0);
if(__new_nstart < _M_start._M_node)
copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart);
else
copy_backward(_M_start._M_node, _M_finish._M_node + 1,
__new_nstart + __old_num_nodes);
}
else {
size_type __new_map_size =
_M_map_size + max(_M_map_size, __nodes_to_add) + 2;
_Map_pointer __new_map = _M_allocate_map(__new_map_size);
__new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2
+ (__add_at_front ? __nodes_to_add : 0);
copy(_M_start._M_node, _M_finish._M_node + 1, __new_nstart);
_M_deallocate_map(_M_map, _M_map_size);
_M_map = __new_map;
_M_map_size = __new_map_size;
}
_M_start._M_set_node(__new_nstart);
_M_finish._M_set_node(__new_nstart + old_num_nodes - 1);
}
void push_back() {
if(_M_finish._M_cur != _M_finish._M_last - 1) {
construct(_M_start._M_cur);
++_M_start._M_cur;
}
else
_M_push_back_aux(__t);
}
push_front
void push_front(const value_type& __t) {
if(_M_start._M_cur != _M_start._M_first) { //
construct(_M_start._M_cur - 1, __t);
--_M_start._M_cur;
}
else
_M_push_front_aux(__t);
}
void _M_push_front_aux(const value_type& __t) {
value_type __t_copy = __t;
_M_reserve_map_at_front();
*(_M_start._M_node - 1) = _M_allocate_node();
_STL_TRY {
_M_start._M_set_node(_M_start._M_node - 1);
_M_start._M_cur = _M_start._M_last - 1;
construct(_M_start._M_cur, __t_copy);
}
__STL_UNWIND(++_M_start, _M_deallocate_node(*(_M_start._M_node - 1)));
}
void push_front() {
if(_M_start._M_cur != _M_start.first) {
construct(_M_start._M_cur - 1);
--_M_start._M_cur;
}
else
_M_push_front_aux();
}
pop_back
void pop_back() {
if(_M_finish._M_cur != _M_finish._M_first) {
--_M_finish._M_cur;
destory(_M_finish._M_cur);
}
else
_M_pop_back_aux();
}
void _M_pop_back_aux() {
_M_deallocate_node(_M_finish._M_first);
_M_finish._M_set_node(_M_finish._M_mode - 1);
_M_finish._M_cur = _M_finish._M_last - 1;
destroy(_M_finish._M_cur);
}
pop_front
void pop_front() {
if(_M_start._M_cur != _M_start._M_last - 1) {
destory(_M_start._M_cur);
--_M_start._M_cur--;
}
else
_M_pop_front_aux();
}
void _M_pop_front_aux() {
destroy(_M_start._M_cur);
_M_deallocate_node(_M_start._M_first);
_M_start._M_set_node(_M_start._M_node + 1);
_M_start._M_cur = _M_start._M_first;
}
Insert
iterator insert(iterator position, const value_type& __x) {
if(position._M_cur == _M_start._M_cur) {
push_front(__x);
return _M_start;
}
else if(position._M_cur == _M_finish._M_cur) {
push_back(__x);
iterator __tmp = _M_finish;
--__tmp;
return __tmp;
}
else {
return _M_insert_aux(position, __x);
}
}
iterator _M_insert_aux(iterator position, const value_type& __x) {
difference_type __index = pos - _M_start;
value_type __x_copy = __x;
if(size_type(__index) < this->size()/2) {
push_front(front());
iterator __front1 = _M_start;
++__front1;
iterator __front2 = __front1;
++front2;
__pos = _M_start + __index;
iterator __pos1 = pos;;
++__pos1;
copy(front2, pos1, front1);
}
else {
push_back(back());
iterator __back1 = _M_finish;
--__back1;
iterator __back2 = __back1;
--__back2;
__pos = _M_start + __index;
copybackward(pos, __back2, __back1);
}
*__pos = __x_copy;
return __pos;
}