deque的实现
- deque是双向开口的一段空间,实质上是分段连续的
- 具体实现如下图,先分段,再将它们串接起来。底层是一个vector,存放指向每一个缓冲区的指针,缓冲区的次序与vector的次序相同。
- 最后一个缓冲区已经被元素填满,再分配一个缓冲区,把它串接到底层的vector中,就可继续向后扩充。如果向前扩充的缓冲区也被填满,再分配一个缓冲区,vector中靠近左端元素的空位置存储新分配缓冲区的指针。当控制中心满了后,会扩容为原来的二倍,类似vector的动态增长。
- deque的迭代器是一个class,它有四个元素。
- node指向底层的vector,当这个迭代器++或–时,它就能跳到另一个缓冲区中
- first指向当前缓冲区的头,last指向当前缓冲区的尾,二者指出缓冲区的边界。如果指针走到了当前缓冲区的边界,它就要通过node指针跳到下一个缓冲区。
- cur是迭代器当前指向的元素(迭代器的作用就是指向一个元素)
- 几乎所有的容器都维护了两个迭代器,分别指向头和尾,begin指向start,end指向finish
G2.9版
- deque的迭代器有4个指针,大小为16,deque有两个迭代器和两个指针,故大小为40
- deque的迭代器要提供五个相关的类型
---------------------BufSize的计算------------------------
inline size_t __deque_buf_size(size_t n, size_t sz)
{
return n != 0 ? n : (sz < 512 ? size_t(512 / sz) : size_t(1));
}
---------------------deque的模板类--------------------
template<class T, class Alloc = alloc, size_t BufSize = 0>
class deque{
public:
typedef T value_type;
typedef __deque_iterator<T, T&, T*, BufSize> iterator;
protected:
typedef pointer* map_pointer;
protected:
iterator start;
iterator finish;
map_pointer map;
size_type map_size;
public:
iterator begin() { return start; }
iterator end() { return finish; }
size_type size() const { return finish - start;}
...
}
------------------------deque的迭代器----------------------
template<class T, class Ref, class Ptr, size_t BifSize>
struct __deque_iterator {
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T** map_pointer;
typedef __deque__iterator self;
T* cur;
T* first;
T* last;
map_pointer node;
...
}
----------------deque<T>::insert---------------------
iterator insert(iterator position, const value_type& x){
if(position.cur == start.cur){
push_front(x);
return start;
} else if (position.cur == end.cur) {
push_back(x);
iterator tmp = finish;
--tmp;
return tmp;
}else {
return insert_aux(position, x);
}
}
template<class T, class Alloc, size_t BufSize>
class deque<T, Alloc, BufSize>::iterator
deque<T, Alloc, BufSize>::insert_sux(iterator pos, const value_type& x){
difference_type index = pos - start;
value_type x_copy = x;
if(index < size() / 2){
push_front(front());
...
copy(front2, posl, front1);
}
else{
push_back(back));
...
copy_backward(pos, back2, back1);
}
*pos = x_copy;
return pos;
}
- deque如何模拟连续空间
- ->依靠迭代器实现
- deque的成员函数
reference operator[](size_type n)
{
return start[difference_type(n)];
}
reference front()
{ return *start; }
reference back()
{
iterator *tmp = finish;
--tmp;
return tmp;
}
size_type size() const
{ return finish - start; }
bool empty()
{ return finish == start; }
reference operator*() const
{ return *cur; }
pointer operator->() const
{ return &(operator*()); }
difference_type
operator- (const self& x) const
{
return difference_type(buffer_size()) * (node - x.cur - 1) + (cur - first) + (x.last - x.cur);
}
void set_node(map_pointer new_node)
{
node = new_node;
first = *new_node;
last = first + difference_type(buffer_size());
}
self& operator++(){
++cur;
if( cur == last){
{
set_node(node + 1);
cur = first;
}
return *this;
}
self operator++(int)
{
selt tmp = *this;
++*this;
return tmp;
}
self& operator--()
{
if(cur == first){
set_node(node - 1);
cur = last;
}
--cur;
return *this;
}
self operator--(int)
{
self tmp = *this;
--*this;
return tmp;
}
self& operator+=(difference_type n){
difference_type offset = n + (cur - first);
if(offset >= 0 && offset < difference_type(buffer_size)))
cur += n;
else{
difference_type node_offset = offset > 0 ? offset / difference_type(buffer_size) : - difference_type((-offset - 1) / buffer_size()) - 1;
set_node(node + node_offset);
cur = first + (offset - node_offset * difference_type(buffer_size()));
}
return *this;
}
self operator+ (difference_type n) const
{
self tmp = *this;
return tmp += n;
}
self& operstor-=(difference_type n)
{ return *this += -n; }
self operator-(difference_type n) const
{
self tmp = *this;
retturn tmp -= n;
}
reference operator[](difference_type n) const
{ return *(*this + n); }
G4.9版
- deque的大小为40
- deque的模板参数变成了两个,取消了设置缓冲区大小的参数
- deque的控制中心底层实现是vector,但是它每次扩容时复制是将元素copy到vector的中段,为了最大限度的保证左右两部分空槽位一样多
queue
- queue可以在deque的基础上封锁一些功能,成为新的一种容器
- queue不用自己定义操作,它提供调用底层的deque容器完成所需操作
template<class T, class Sequence = deque<T>>
class queue{
...
public:
typedef typename Sequence::value_type value_type;
typedef typename Sequence::size_type size_type;
typedef typename Sequence::reference reference;
typedef typename Sequence::const_reference const_reference;
protected:
Sequence c;
public:
bool empty() const { return c.empty(); }
size_type size() const { return c.size(); }
reference front() { return c.front(); }
const_reference front() const { return c.front(); }
reference back() { return c.back(); }
const_reference back() const { return c.back(); }
void push(const value_type& x) { c.push_back(x); }
void pop() { c.pop_front(); }
};
stack
- stack内含了一个deque,它通过调用底层的deque的接口来实现功能
template<class T, class Sequence = deque<T>>
class stack{
...
public:
typedef typename Sequence::value_type value_type;
typedef typename Sequence::size_type size_type;
typedef typename Sequence::reference reference;
typedef typename Sequence::const_reference const_reference;
protected:
Sequence c;
public:
bool empty() const{return c.empty(); }
size_type size() const { return c.size(); }
reference top() { return c.back(); }
const_reference top() { return c.back(); }
void push(const value_type& x) { c.push_back(x);}
void pop(){ c.pop_back); }
};
stack和queue
- list和deque都可以作为它们的底层结构
- stack和deque都不允许遍历,也不提供iterator,也不允许insert
- stack可以选择vector做底层容器,但是queue不能选vector做底层容器
- vector没有pop_front
- 编译器对于模板的检查不是全面的检查,一部分函数在使用前是不会检查的
- stack和queue都不可以选择set和map做底层容器