队列和双端队列源码分析--queue、deque

queue 模板类的定义在<queue>头文件中。与stack 模板类很相似,queue 模板类也需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型。定义queue 对象的示例代码如下:queue< int> q1;

queue< double > q2;

queue 的基本操作有:入队,如例:q.push(x); 将x 接到队列的末端。出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。访问队首元素,如例:q.front(),即最早被压入队列的元素。访问队尾元素,如例:q.back(),即最后被压入队列的元素。判断队列空,如例:q.empty(),当队列空时,返回true。访问队列中的元素个数,如例:q.size()

stl_queue.h的源码:

// queue是一种先进先出(First In First Out, FIFO)的数据结构

// 它在前后有两个出口, 分别成为队头和队尾

// queue允许在队尾追加元素和访问队尾元素, 在队头获取和移除元素

// 除此之外其不支持其它元素的访问

// 以下为使用deque时的布局

//

// 支持front()和pop() 支持back()和push()

// ↓ ↓

// 队头, 队尾

// ↓ ↓

// ---------------------------------------------------------------------

// | | | ...... | | | ...... | | | | ...... | | | X |

// ---------------------------------------------------------------------

// ↑ ↑ ↑ ↑

// | | | |

// ---------------------- -----------------------

// 这里是尚未使用的预留内存, 可能为0 这里是尚未使用的预留内存, 可能为0

//

// priority_queue是一种允许用户以任何顺序将任何元素压入容器,

// 但是取出元素时一定是从最高优先级的元素开始取出

// 其默认使用的是vector作为容器, 默认的优先级比较使用less

// 其算法是使用binary-heap

// 下面是其原理模型, 容器使用vector, 优先级比较决议用less

//

// 队尾, 支持push()

// ↓

// --------------------------------------------------------

// 支持pop()和top()--->| | | ...... | | | | | ...... | | | X |

// --------------------------------------------------------

// ↑ ↑ ↑

// | -----------------------

// 内部使用的是heap 这里是尚未使用的预留内存, 可能为0

// 下面是容器使用vector, 优先级比较决议用less的情况下的一种实现技巧,

// 借用的是侯捷老师的例子, 本实作中使用的不是此技巧

// [A]

// |

// ---------------------------------

// | |

// [B] [C]

// | |

// ----------------------- -----------------------

// | | | |

// [D] [E] [F] [G]

// | |

// ----------- |

// | | |

// [H] [I] [J]

// vector中预留的内存, 了能为0

// ------------------

// ↓ ↓

// --------------------------------------------------------------------------

// | Not Use | A | B | C | D | E | F | G | H | I | J | | ...... | | end |

// --------------------------------------------------------------------------

//

// 具体算法请参看任意一本算法书, 如果没有, 扔了它:-)

/*
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.  Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose.  It is provided "as is" without express or implied warranty.
*
*
* Copyright (c) 1996,1997
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation.  Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose.  It is provided "as is" without express or implied warranty.
*/
 
/* NOTE: This is an internal header file, included by other STL headers.
*   You should not attempt to use it directly.
*/
 
#ifndef __SGI_STL_INTERNAL_QUEUE_H
#define __SGI_STL_INTERNAL_QUEUE_H
 
__STL_BEGIN_NAMESPACE
 
// 如果编译器不能根据前面模板参数推导出后面使用的默认参数类型,
// 那么就需要手工指定, 本实作queue内部容器默认使用deque
// 由于queue要求在队尾追加元素, 在队头获取和移除元素
// 所以非常适合使用deque
#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
template<classT, classSequence=deque<T>>
#else
template<classT, classSequence>
#endif
classqueue
{
  // 讲解见<stl_pair.h>中的运算符剖析
  friendbooloperator==__STL_NULL_TMPL_ARGS (constqueue&x, constqueue&y);
  friendbooloperator<__STL_NULL_TMPL_ARGS (constqueue&x, constqueue&y);
 
public:
  // 由于queue仅支持对队头和队尾的操作, 所以不定义STL要求的
  // pointer, iterator, difference_type
  typedeftypenameSequence::value_typevalue_type;
  typedeftypenameSequence::size_typesize_type;
  typedeftypenameSequence::referencereference;
  typedeftypenameSequence::const_referenceconst_reference;
 
protected:
  Sequencec;   // 这个是我们实际维护的容器
 
public:
 
  // 这些是STL queue的标准接口, 都调用容器的成员函数进行实现
  // 其接口和stack实现很接近, 参考<stl_stack.h>
  boolempty() const { returnc.empty(); }
  size_typesize() const { returnc.size(); }
  referencefront() { returnc.front(); }
  const_referencefront() const { returnc.front(); }
  referenceback() { returnc.back(); }
  const_referenceback() const { returnc.back(); }
  voidpush(constvalue_type&x) { c.push_back(x); }
  voidpop() { c.pop_front(); }
};
 
// 详细讲解见<stl_pair.h>
template<classT, classSequence>
booloperator==(constqueue<T, Sequence>&x, constqueue<T, Sequence>&y)
{
  returnx.c==y.c;
}
 
template<classT, classSequence>
booloperator<(constqueue<T, Sequence>&x, constqueue<T, Sequence>&y)
{
  returnx.c<y.c;
}
 
#ifndef __STL_LIMITED_DEFAULT_TEMPLATES
template<classT, classSequence=vector<T>,
          classCompare=less<typenameSequence::value_type>>
#else
template<classT, classSequence, classCompare>
#endif
class  priority_queue
{
public:
  typedeftypenameSequence::value_typevalue_type;
  typedeftypenameSequence::size_typesize_type;
  typedeftypenameSequence::referencereference;
  typedeftypenameSequence::const_referenceconst_reference;
 
protected:
  Sequencec;           // 内部维护的容器
  Comparecomp;         // 优先级决策判别式
 
public:
  priority_queue() : c() {}
 
  // 用户可以指定自己的优先级决策函数
  explicitpriority_queue(constCompare&x) :  c(), comp(x) {}
 
// 使用[first, last)区间构造priority_queue
#ifdef __STL_MEMBER_TEMPLATES
  template<classInputIterator>
  priority_queue(InputIteratorfirst, InputIteratorlast, constCompare&x)
    : c(first, last), comp(x) { make_heap(c.begin(), c.end(), comp); }
  template<classInputIterator>
  priority_queue(InputIteratorfirst, InputIteratorlast)
    : c(first, last) { make_heap(c.begin(), c.end(), comp); }
#else /* __STL_MEMBER_TEMPLATES */
  priority_queue(constvalue_type*first, constvalue_type*last,
                 constCompare&x) : c(first, last), comp(x) {
    make_heap(c.begin(), c.end(), comp);
  }
  priority_queue(constvalue_type*first, constvalue_type*last)
    : c(first, last) { make_heap(c.begin(), c.end(), comp); }
#endif /* __STL_MEMBER_TEMPLATES */
 
  // STL priority_queue标准接口
  boolempty() const { returnc.empty(); }
  size_typesize() const { returnc.size(); }
 
  // 返回优先级最高的元素
  const_referencetop() const { returnc.front(); }
 
  // 插入元素, 并调整heap
  voidpush(constvalue_type&x)
  {
    __STL_TRY {
      c.push_back(x);
      // 详细分析见<stl_heap.h>
      push_heap(c.begin(), c.end(), comp);
    }
    __STL_UNWIND(c.clear());
  }
 
  // 弹出优先级最高的元素
  voidpop() {
    __STL_TRY {
      // 详细分析见<stl_heap.h>
      pop_heap(c.begin(), c.end(), comp);
      c.pop_back();
    }
    __STL_UNWIND(c.clear());
  }
};
 
// 不提供比较操作
 
__STL_END_NAMESPACE
 
#endif /* __SGI_STL_INTERNAL_QUEUE_H */
 
// Local Variables:
// mode:C++
// End:

deque不只是可以再尾端插入,也可以在队列头插入。deque在STL中是维护多个连续内存的,多个连续的内存不一定连续,一段连续的内存叫做缓冲区。deque的迭代器有4个元素,cur指向当前所指的deque结点,first指向迭代器所指结点所在缓冲区的起始位置,last指向迭代器所指结点所在缓冲区的结尾位置,node指向中控器的某个位置,这个位置指向迭代器所指结点所在的缓冲区。

stl_deque.h源码:

// 如果vector能满足你的需求, 那么就使用vector

// 如果不得不使用deque, 那么在进行一算法(尤其是sort)操作时

// 应该先把deque中的元素复制到vector中

// 执行完算法再复制回去

// 这样的效率往往要高于直接使用算法的效率

/*
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Hewlett-Packard Company makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 *
 *
 * Copyright (c) 1997
 * Silicon Graphics Computer Systems, Inc.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  Silicon Graphics makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 */
/* NOTE: This is an internal header file, included by other STL headers.
 *   You should not attempt to use it directly.
 */
 
#ifndef __SGI_STL_INTERNAL_DEQUE_H
#define __SGI_STL_INTERNAL_DEQUE_H
 
// 特性:
//   对于任何的非奇异(nonsingular)的迭代器i
//     i.node是map array中的某元素的地址. i.node的内容是一个指向某个结点的头的指针
//     i.first == *(i.node)
//     i.last  == i.first + node_size
//     i.cur是一个指向[i.first, i.last)之间的指针
//       注意: 这意味着i.cur永远是一个可以解引用的指针,
//            即使其是一个指向结尾后元素的迭代器
//
//   起点和终点总是非奇异(nonsingular)的迭代器.
//     注意: 这意味着空deque一定有一个node, 而一个具有N个元素的deque
//          (N是Buffer Size)一定有有两个nodes
//
//   对于除了start.node和finish.node之外的每一个node, 每一个node中的元素
//   都是一个初始化过的对象. 如果start.node == finish.node,
//   那么[start.cur, finish.cur)都是未初始化的空间.
//   否则, [start.cur, start.last)和[finish.first, finish.cur)都是初始化的对象,
//   而[start.first, start.cur)和[finish.cur, finish.last)是未初始化的空间
//
//   [map, map + map_size)是一个合法的非空区间
//   [start.node, finish.node]是内含在[map, map + map_size)区间的合法区间
//   一个在[map, map + map_size)区间内的指针指向一个分配过的node,
//   当且仅当此指针在[start.node, finish.node]区间内
 
// 在前一个版本的deque中, node_size被设定为定植.
// 然而在这个版本中, 用户可以自定义node_size的大小.
// deque有三个模板参数, 第三个参数为size_t类型, 代表每个结点内的元素数目.
// 如果第三个参数被设定为0(默认值), deque使用默认结点大小
//
// 使用不同结点大小的唯一理由是, 你的程序需要不同的效率, 并愿意为此付出代价,
// 例如, 如果你的程序中有许多deque, 但是每个deque都只包含很少的元素,
// 那么你可以使用较小的node_size来进行管理, 但是会对访问操作带来效率损失
//
 
// 不幸的是, 一些编译器不能正确处理non-type template parameters;
// 如果这样, 在<stl_config.h>会定义__STL_NON_TYPE_TMPL_PARAM_BUG
// 如果你的编译器不幸在列, 你只能使用默认的大小, 而不能更改
 
__STL_BEGIN_NAMESPACE
 
#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)
#pragma set woff 1174
#endif
 
// 这个函数是为了防止不同编译器在处理常量表达式时的Bug
// 如果n != 0, 那么就返回n, 表示buffer size为使用者自定义
// 如果n ==0, 就返回默认值表示buffer size,默认值计算方法如下
//    如果sz(元素类型大小sizeof(type))小于512, 返回512 / sz
//    否则返回1
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));
}
 
// 注意这里未继承自std::iterator
#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
template <class T, class Ref, class Ptr, size_t BufSiz>
struct __deque_iterator {
  typedef __deque_iterator<T, T&, T*, BufSiz>             iterator;
  typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;
  static size_t buffer_size() {return __deque_buf_size(BufSiz, sizeof(T)); }
#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
template <class T, class Ref, class Ptr>
struct __deque_iterator {
  typedef __deque_iterator<T, T&, T*>             iterator;
  typedef __deque_iterator<T, const T&, const T*> const_iterator;
  static size_t buffer_size() {return __deque_buf_size(0, sizeof(T)); }
#endif
 
  typedef random_access_iterator_tag iterator_category;      // STL标准强制要求
  typedef T value_type;                                      // STL标准强制要求
  typedef Ptr pointer;                                       // STL标准强制要求
  typedef Ref reference;                                     // STL标准强制要求
  typedef size_t size_type;
  typedef ptrdiff_t difference_type;                         // STL标准强制要求
  typedef T** map_pointer;
  typedef __deque_iterator self;
 
  // 保存容器中的结点
  T* cur;       // 指向当前缓冲区中的元素
  T* first;     // 当前缓冲区的起点
  T* last;      // 当前缓冲区的终点

// 这个是deque内存管理的关键, 其模型如下

//

// ---------------------------------------------

// map-->| | | | | | | ..... | | | |<------------------

// --------------------------------------------- |

// | |

// | |

// | node |

// | 缓冲区buffer, 这里实际存储元素 |

// | --------------------------------------------- |

// --->| | | | | | | ..... | | | X | |

// --------------------------------------------- |

// ↑ ↑ ↑ |

// ------ | | |

// | | | |

// | ----------- --------------------------- |

// ----|----- | |

// | | | |

// | | | |

// | | | |

// --------------------------- |

// | cur | first | end | map |------------------------------

// ---------------------------

// 迭代器, 其内部维护着一个缓冲区状态

  map_pointer node;
 
  __deque_iterator(T* x, map_pointer y)
    : cur(x), first(*y), last(*y + buffer_size()), node(y) {}
  __deque_iterator() : cur(0), first(0), last(0), node(0) {}
  __deque_iterator(const iterator& x)
    : cur(x.cur), first(x.first), last(x.last), node(x.node) {}
 
  reference operator*() const { return *cur; }
 
#ifndef __SGI_STL_NO_ARROW_OPERATOR
  // 如果编译器支持'->'则重载, 详细见我在<stl_list.h>中的剖析
  pointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
 
  // 判断两个迭代器间的距离
 
  difference_type operator-(const self& x) const
  {
    return difference_type(buffer_size()) * (node - x.node - 1) +
      (cur - first) + (x.last - x.cur);
  }
 
 
// 下面重载的这些是运算符是让deque从外界看上去维护的是一段连续空间的关键!!!
 
 
 
// 前缀自增
 
// 如果当前迭代器指向元素是当前缓冲区的最后一个元素,
// 则将迭代器状态调整为下一个缓冲区的第一个元素
 
// 不是当前缓冲区最后一个元素
//
// 执行前缀自增前的状态
// first          cur                     end
// ↓               ↓                       ↓
// ---------------------------------------------
// |   |   |   |   |   |   | ..... |   |   | X | <----- 当前缓冲区
// ---------------------------------------------
//
// 执行完成后的状态
// first              cur                 end
// ↓                   ↓                   ↓
// ---------------------------------------------
// |   |   |   |   |   |   | ..... |   |   | X | <----- 当前缓冲区
// ---------------------------------------------
//
 
// 当前元素为当前缓冲区的最后一个元素
//
// 执行前缀自增前的状态
// first                              cur end
// ↓                                   ↓   ↓
// ---------------------------------------------
// |   |   |   |   |   |   | ..... |   |   | X | <----- 当前缓冲区
// ---------------------------------------------
//
// 执行完成后的状态
// first                                  end
// ↓                                       ↓
// ---------------------------------------------
// |   |   |   |   |   |   | ..... |   |   | X | <----- 下一缓冲区
// ---------------------------------------------
// ↑
// cur
//
 
  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_node(node - 1);
      cur = last;
    }
    --cur;
    return *this;
  }
 
  self operator--(int)
  {
    self tmp = *this;
    --*this;
    return tmp;
  }
 
 
// 将迭代器向前移动n个元素, n可以为负
 
//                     operator+=(difference_type n)
//                                   ↓
//                      offset = n + (cur - first)
//                                   |
//                                   |---------- offset > 0 ? &&
//                                   |           移动后是否超出当前缓冲区?
//               ----------------------------
//           No  |                          |  Yes
//               |                          |
//               ↓                          |---------- offset > 0?
//           cur += n;                      |
//                              ----------------------------
//                          Yes |                          | No
//                              |                          |
//                              ↓                          |
//                   计算要向后移动多少个缓冲区                |
//                   node_offset =                         |
//                   offset / difference_type              |
//                   (buffer_size());                      ↓
//                              |           计算要向前移动多少个缓冲区
//                              |           node_offset = -difference_type
//                              |           ((-offset - 1) / buffer_size()) - 1;
//                              |                          |
//                              ----------------------------
//                                           |
//                                           |
//                                           ↓
//                                       调整缓冲区
//                              set_node(node + node_offset);
//                                    计算并调整cur指针
 
 
  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;
 
    // 这里调用了operator +=()可以自动调整指针状态
    return tmp += n;
  }
 
  // :-), 将n变为-n就可以使用operator +=()了,
  // 初等数学是神奇的, 还记得我们刚学编程时求绝对值是怎么写的吗? :P
  self& operator-=(difference_type n) { return *this += -n; }
 
  self operator-(difference_type n) const {
    self tmp = *this;
    return tmp -= n;
  }
 
  reference operator[](difference_type n) const { return *(*this + n); }
 
  bool operator==(const self& x) const { return cur == x.cur; }
  bool operator!=(const self& x) const { return !(*this == x); }
  bool operator<(const self& x) const {
    return (node == x.node) ? (cur < x.cur) : (node < x.node);
  }
 
  void set_node(map_pointer new_node)
  {
    node = new_node;
    first = *new_node;
    last = first + difference_type(buffer_size());
  }
};
 
#ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
 
#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
 
template <class T, class Ref, class Ptr, size_t BufSiz>
inline random_access_iterator_tag
iterator_category(const __deque_iterator<T, Ref, Ptr, BufSiz>&) {
  return random_access_iterator_tag();
}
 
template <class T, class Ref, class Ptr, size_t BufSiz>
inline T* value_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) {
  return 0;
}
 
template <class T, class Ref, class Ptr, size_t BufSiz>
inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr, BufSiz>&) {
  return 0;
}
 
#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
 
template <class T, class Ref, class Ptr>
inline random_access_iterator_tag
iterator_category(const __deque_iterator<T, Ref, Ptr>&) {
  return random_access_iterator_tag();
}
 
template <class T, class Ref, class Ptr>
inline T* value_type(const __deque_iterator<T, Ref, Ptr>&) { return 0; }
 
template <class T, class Ref, class Ptr>
inline ptrdiff_t* distance_type(const __deque_iterator<T, Ref, Ptr>&) {
  return 0;
}
 
#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
 
// 其实剖析到这里就没有什么难的了, deque的运算符才是核心
#endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
 
// See __deque_buf_size().  The only reason that the default value is 0
//  is as a workaround for bugs in the way that some compilers handle
//  constant expressions.
template <class T, class Alloc = alloc, size_t BufSiz = 0>
class deque {
public:                         // Basic types
  typedef T 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;
 
public:                         // Iterators
#ifndef __STL_NON_TYPE_TMPL_PARAM_BUG
  typedef __deque_iterator<T, T&, T*, BufSiz>              iterator;
 
  typedef __deque_iterator<T, const T&, const T&, BufSiz>  const_iterator;
#else /* __STL_NON_TYPE_TMPL_PARAM_BUG */
  typedef __deque_iterator<T, T&, T*>                      iterator;
  typedef __deque_iterator<T, const T&, const T*>          const_iterator;
#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
 
#ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
  typedef reverse_iterator<const_iterator> const_reverse_iterator;
  typedef reverse_iterator<iterator> reverse_iterator;
#else /* __STL_CLASS_PARTIAL_SPECIALIZATION */
  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 /* __STL_CLASS_PARTIAL_SPECIALIZATION */
 
protected:                      // Internal typedefs
 
  typedef pointer* map_pointer;
 
  // 这个提供STL标准的allocator接口, 见<stl_alloc.h>
  typedef simple_alloc<value_type, Alloc> data_allocator;
  typedef simple_alloc<pointer, Alloc> map_allocator;
 
  // 获取缓冲区最大存储元素数量
  static size_type buffer_size()
  {
    return __deque_buf_size(BufSiz, sizeof(value_type));
  }
 
  static size_type initial_map_size() { return 8; }
 
protected:                      // Data members
  iterator start;               // 起始缓冲区
  iterator finish;              // 最后一个缓冲区
 
  // 指向map, map是一个连续的空间, 其每个元素都是一个指向缓冲区的指针
  // 其模型见前面的__deque_iterator
  map_pointer map;
  size_type map_size;   // map容量
 public:                         // Basic accessors
  iterator begin() { return start; }
  iterator end() { return finish; }
  const_iterator begin() const { return start; }
  const_iterator end() const { return finish; }
 
  reverse_iterator rbegin() { return reverse_iterator(finish); }
  reverse_iterator rend() { return reverse_iterator(start); }
  const_reverse_iterator rbegin() const {
    return const_reverse_iterator(finish);
  }
  const_reverse_iterator rend() const {
    return const_reverse_iterator(start);
  }
 
  // 提供随机访问能力, 其调用的是迭代器重载的operator []
  // 其实际地址需要进行一些列的计算, 效率有损失
  reference operator[](size_type n) { return start[difference_type(n)]; }
  const_reference operator[](size_type n) const {
    return start[difference_type(n)];
  }
 
  reference front() { return *start; }
  reference back() {
    iterator tmp = finish;
    --tmp;
    return *tmp;
  }
  const_reference front() const { return *start; }
  const_reference back() const {
    const_iterator tmp = finish;
    --tmp;
    return *tmp;
  }
 
  // 当前容器拥有的元素个数, 调用迭代器重载的operator -
  size_type size() const { return finish - start;; }
  size_type max_size() const { return size_type(-1); }
 
  // deque为空的时, 只有一个缓冲区
  bool empty() const { return finish == start; }
 
public:                         // Constructor, destructor.
  deque()
    : start(), finish(), map(0), map_size(0)
  {
    create_map_and_nodes(0);
  }
 
  // 注: commit or rollback
  deque(const deque& x)
    : start(), finish(), map(0), map_size(0)
  {
    create_map_and_nodes(x.size());
    __STL_TRY {
      uninitialized_copy(x.begin(), x.end(), start);  // <stl_uninitialized.h>
    }
    __STL_UNWIND(destroy_map_and_nodes());
  }
 
  deque(size_type n, const value_type& value)
    : start(), finish(), map(0), map_size(0)
  {
    fill_initialize(n, value);
  }
 
  deque(int n, const value_type& value)
    : start(), finish(), map(0), map_size(0)
  {
    fill_initialize(n, value);
  }
 
  deque(long n, const value_type& value)
    : start(), finish(), map(0), map_size(0)
  {
    fill_initialize(n, value);
  }
 
  explicit deque(size_type n)
    : start(), finish(), map(0), map_size(0)
  {
    fill_initialize(n, value_type());
  }
 
#ifdef __STL_MEMBER_TEMPLATES
 
  template <class InputIterator>
  deque(InputIterator first, InputIterator last)
    : start(), finish(), map(0), map_size(0)
  {
    range_initialize(first, last, iterator_category(first));
  }
 
#else /* __STL_MEMBER_TEMPLATES */
 
  deque(const value_type* first, const value_type* last)
    : start(), finish(), map(0), map_size(0)
  {
    create_map_and_nodes(last - first);
    __STL_TRY {
      uninitialized_copy(first, last, start);
    }
    __STL_UNWIND(destroy_map_and_nodes());
  }
 
  deque(const_iterator first, const_iterator last)
    : start(), finish(), map(0), map_size(0)
  {
    create_map_and_nodes(last - first);
    __STL_TRY {
      uninitialized_copy(first, last, start);
    }
    __STL_UNWIND(destroy_map_and_nodes());
  }
 
#endif /* __STL_MEMBER_TEMPLATES */
 
  ~deque()
  {
    destroy(start, finish);     // <stl_construct.h>
    destroy_map_and_nodes();
  }
 
  deque& operator= (const deque& x)
  {
    // 其实我觉得把这个操作放在if内效率更高
    const size_type len = size();
    if (&x != this) {
      // 当前容器比x容器拥有元素多, 析构多余元素
      if (len >= x.size())
        erase(copy(x.begin(), x.end(), start), finish);
      // 将x所有超出部分的元素使用insert()追加进去
      else {
        const_iterator mid = x.begin() + difference_type(len);
        copy(x.begin(), mid, start);
        insert(finish, mid, x.end());
      }
    }
    return *this;
  }
 
  // 其实要交换两个容器, 只需要交换其内部维护的指针即可^_^
  void swap(deque& x)
  {
    __STD::swap(start, x.start);
    __STD::swap(finish, x.finish);
    __STD::swap(map, x.map);
    __STD::swap(map_size, x.map_size);
  }
 
public:                         // push_* and pop_*
 
  void push_back(const value_type& t)
  {
    // STL使用前闭后开的区间, 所以如果还有剩余容量,
    // 则直接在finish.cur上构造对象即可, 然后更新迭代器
    if (finish.cur != finish.last - 1) {
      construct(finish.cur, t);
      ++finish.cur;
    }
    // 容量已满就要新申请内存了
    else
      push_back_aux(t);
  }
 
  void push_front(const value_type& t)
  {
    if (start.cur != start.first) {
      construct(start.cur - 1, t);
      --start.cur;
    }
    else
      push_front_aux(t);
  }
 
  void pop_back()
  {
    if (finish.cur != finish.first) {
      --finish.cur;
      destroy(finish.cur);
    }
    else
      pop_back_aux();
  }
 
  void pop_front() {
    if (start.cur != start.last - 1)
    {
      destroy(start.cur);
      ++start.cur;
    }
    else
      pop_front_aux();
  }
 
public:                         // Insert
 
 
// 在指定位置前插入元素
 
//             insert(iterator position, const value_type& x)
//                                   |
//                                   |---------------- 判断插入位置
//                                   |
//               -----------------------------------------------
// deque.begin() |          deque.emd() |                      |
//               |                      |                      |
//               ↓                      ↓                      |
//         push_front(x);         push_back(x);                |
//                                                             ↓
//                                                 insert_aux(position, x);
//                                                 具体剖析见后面实现
 
 
  iterator insert(iterator position, const value_type& x)
  {
    // 如果是在deque的最前端插入, 那么直接push_front()即可
    if (position.cur == start.cur) {
      push_front(x);
      return start;
    }
    // 如果是在deque的末尾插入, 直接调用push_back()
    else if (position.cur == finish.cur) {
      push_back(x);
      iterator tmp = finish;
      --tmp;
      return tmp;
    }
    else {
      return insert_aux(position, x);
    }
  }
 
  iterator insert(iterator position) { return insert(position, value_type()); }
 
  // 详解见实现部分
  void insert(iterator pos, size_type n, const value_type& x);
 
  void insert(iterator pos, int n, const value_type& x)
  {
    insert(pos, (size_type) n, x);
  }
  void insert(iterator pos, long n, const value_type& x)
  {
    insert(pos, (size_type) n, x);
  }
 
#ifdef __STL_MEMBER_TEMPLATES
 
  template <class InputIterator>
  void insert(iterator pos, InputIterator first, InputIterator last)
  {
    insert(pos, first, last, iterator_category(first));
  }
 
#else /* __STL_MEMBER_TEMPLATES */
 
  void insert(iterator pos, const value_type* first, const value_type* last);
  void insert(iterator pos, const_iterator first, const_iterator last);
 
#endif /* __STL_MEMBER_TEMPLATES */
 
  // 如果new_size < size(), 那么就析构掉多余的元素,
  // 否则以x为蓝本进行剩余元素的填充
  void resize(size_type new_size, const value_type& x)
  {
    const size_type len = size();
    if (new_size < len)
      erase(start + new_size, finish);
    else
      insert(finish, new_size - len, x);
  }
 
  void resize(size_type new_size) { resize(new_size, value_type()); }
 
public:                         // Erase
 
  iterator erase(iterator pos)
  {
    iterator next = pos;
    ++next;
 
    // 计算待擦除点前的元素个数
    difference_type index = pos - start;
 
    // 判断待擦除结点前后元素的个数, 哪部分少就移动哪部分
    if (index < (size() >> 1))
    {
      // 前面部分的元素少
      copy_backward(start, pos, next);  // <stl_algobase.h>
      pop_front();
    }
    // 后面部分的元素少
    else {
      copy(next, finish, pos);          // <stl_algobase.h>
      pop_back();
    }
    return start + index;
  }
 
  // 详解见实现部分
  iterator erase(iterator first, iterator last);
  void clear();
 
protected:                        // Internal construction/destruction
 
  // 详解见实现部分
  void create_map_and_nodes(size_type num_elements);
  void destroy_map_and_nodes();
  void fill_initialize(size_type n, const value_type& value);
 
#ifdef __STL_MEMBER_TEMPLATES
 
  template <class InputIterator>
  void range_initialize(InputIterator first, InputIterator last,
                        input_iterator_tag);
 
  template <class ForwardIterator>
  void range_initialize(ForwardIterator first, ForwardIterator last,
                        forward_iterator_tag);
 
#endif /* __STL_MEMBER_TEMPLATES */
 
protected:                        // Internal push_* and pop_*
 
  // 详解见实现部分
  void push_back_aux(const value_type& t);
  void push_front_aux(const value_type& t);
  void pop_back_aux();
  void pop_front_aux();
 
protected:                        // Internal insert functions
 
#ifdef __STL_MEMBER_TEMPLATES
 
  template <class InputIterator>
  void insert(iterator pos, InputIterator first, InputIterator last,
              input_iterator_tag);
 
  template <class ForwardIterator>
  void insert(iterator pos, ForwardIterator first, ForwardIterator last,
              forward_iterator_tag);
 
#endif /* __STL_MEMBER_TEMPLATES */
 
  iterator insert_aux(iterator pos, const value_type& x);
  void insert_aux(iterator pos, size_type n, const value_type& x);
 
#ifdef __STL_MEMBER_TEMPLATES
 
  template <class ForwardIterator>
  void insert_aux(iterator pos, ForwardIterator first, ForwardIterator last,
                  size_type n);
 
#else /* __STL_MEMBER_TEMPLATES */
 
  void insert_aux(iterator pos,
                  const value_type* first, const value_type* last,
                  size_type n);
 
  void insert_aux(iterator pos, const_iterator first, const_iterator last,
                  size_type n);
 
#endif /* __STL_MEMBER_TEMPLATES */
 
  // 在起始缓冲区预留大小为n的空间
  // 如果缓冲区不足则重新分配
  iterator reserve_elements_at_front(size_type n)
  {
    size_type vacancies = start.cur - start.first;
    if (n > vacancies)
      new_elements_at_front(n - vacancies);
    return start - difference_type(n);
  }
 
  iterator reserve_elements_at_back(size_type n)
  {
    size_type vacancies = (finish.last - finish.cur) - 1;
    if (n > vacancies)
      new_elements_at_back(n - vacancies);
    return finish + difference_type(n);
  }
 
  void new_elements_at_front(size_type new_elements);
  void new_elements_at_back(size_type new_elements);
 
  void destroy_nodes_at_front(iterator before_start);
  void destroy_nodes_at_back(iterator after_finish);
 
protected:                      // Allocation of map and nodes
 
  // Makes sure the map has space for new nodes.  Does not actually
  //  add the nodes.  Can invalidate map pointers.  (And consequently,
  //  deque iterators.)
 
  void reserve_map_at_back (size_type nodes_to_add = 1)
  {
    if (nodes_to_add + 1 > map_size - (finish.node - map))
      reallocate_map(nodes_to_add, false);
  }
 
  void reserve_map_at_front (size_type nodes_to_add = 1)
  {
    if (nodes_to_add > start.node - map)
      reallocate_map(nodes_to_add, true);
  }
 
  void reallocate_map(size_type nodes_to_add, bool add_at_front);
 
  // 分配内存, 不进行构造
  pointer allocate_node() { return data_allocator::allocate(buffer_size()); }
 
  // 释放内存, 不进行析构
  void deallocate_node(pointer n)
  {
    data_allocator::deallocate(n, buffer_size());
  }
 
#ifdef __STL_NON_TYPE_TMPL_PARAM_BUG
public:
  bool operator==(const deque<T, Alloc, 0>& x) const {
    return size() == x.size() && equal(begin(), end(), x.begin());
  }
  bool operator!=(const deque<T, Alloc, 0>& x) const {
    return size() != x.size() || !equal(begin(), end(), x.begin());
  }
  bool operator<(const deque<T, Alloc, 0>& x) const {
    return lexicographical_compare(begin(), end(), x.begin(), x.end());
  }
#endif /* __STL_NON_TYPE_TMPL_PARAM_BUG */
};
 
 
// 不进行内联的成员函数
 
 
 
// 在指定位置前插入n个值为x的元素
 
//           insert(iterator pos, size_type n, const value_type& x)
//                                   |
//                                   |---------------- 判断插入位置
//                                   |
//               ---------------------------------------------------------
// deque.begin() |                    deque.end() |                      |
//               |                                |                      |
//               ↓                                |                      |
// reserve_elements_at_front(n);                  |                      |
// uninitialized_fill(new_start, start, x);       |                      |
//                                                ↓                      |
//                          reserve_elements_at_back(n);                 |
//                          uninitialized_fill(finish, new_finish, x);   |
//                                                                       ↓
//                                                       insert_aux(pos, n, x);
//                                                       剖析见后面实现
 
 
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert(iterator pos,
                                      size_type n, const value_type& x)
{
  if (pos.cur == start.cur) {
    iterator new_start = reserve_elements_at_front(n);
    uninitialized_fill(new_start, start, x);
    start = new_start;
  }
  else if (pos.cur == finish.cur) {
    iterator new_finish = reserve_elements_at_back(n);
    uninitialized_fill(finish, new_finish, x);
    finish = new_finish;
  }
  else
    insert_aux(pos, n, x);
}
 
// 给不支持成员函数模板的编译器提供支持函数
#ifndef __STL_MEMBER_TEMPLATES
 
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert(iterator pos,
                                      const value_type* first,
                                      const value_type* last) {
  size_type n = last - first;
  if (pos.cur == start.cur) {
    iterator new_start = reserve_elements_at_front(n);
    __STL_TRY {
      uninitialized_copy(first, last, new_start);
      start = new_start;
    }
    __STL_UNWIND(destroy_nodes_at_front(new_start));
  }
  else if (pos.cur == finish.cur) {
    iterator new_finish = reserve_elements_at_back(n);
    __STL_TRY {
      uninitialized_copy(first, last, finish);
      finish = new_finish;
    }
    __STL_UNWIND(destroy_nodes_at_back(new_finish));
  }
  else
    insert_aux(pos, first, last, n);
}
 
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert(iterator pos,
                                      const_iterator first,
                                      const_iterator last)
{
  size_type n = last - first;
  if (pos.cur == start.cur) {
    iterator new_start = reserve_elements_at_front(n);
    __STL_TRY {
      uninitialized_copy(first, last, new_start);
      start = new_start;
    }
    __STL_UNWIND(destroy_nodes_at_front(new_start));
  }
  else if (pos.cur == finish.cur) {
    iterator new_finish = reserve_elements_at_back(n);
    __STL_TRY {
      uninitialized_copy(first, last, finish);
      finish = new_finish;
    }
    __STL_UNWIND(destroy_nodes_at_back(new_finish));
  }
  else
    insert_aux(pos, first, last, n);
}
 
#endif /* __STL_MEMBER_TEMPLATES */
 
 
// 擦除[first, last)区间的元素
 
//                  erase(iterator first, iterator last)
//                                   |
//                                   |---------------- 是否要删除整个区间?
//                                   |
//               ------------------------------------------
//           Yes |                                        | No
//               |                                        |
//               ↓                                        | --- 判断哪侧元素少
//            clear();                                    ↓
//       -----------------------------------------------------------------
// 左侧少 |                                                         右侧少 |
//       |                                                               |
//       ↓                                                               ↓
//   copy_backward(start, first, last);            copy(last, finish, first);
//   new_start = start + n;                        new_finish = finish - n;
//   析构多余的元素                                  析构多余的元素
//   destroy(start, new_start);                    destroy(new_finish, finish);
//   释放多余内存空间                                释放多余内存空间
//   for (...)                                     for (...)
//      ...                                             ...
//   更新map状态                                    更新map状态
 
template <class T, class Alloc, size_t BufSize>
deque<T, Alloc, BufSize>::iterator
deque<T, Alloc, BufSize>::erase(iterator first, iterator last)
{
  if (first == start && last == finish) {
    clear();
    return finish;
  }
  else {
    difference_type n = last - first;
    difference_type elems_before = first - start;
    if (elems_before < (size() - n) / 2) {
      copy_backward(start, first, last);
      iterator new_start = start + n;
      destroy(start, new_start);
      for (map_pointer cur = start.node; cur < new_start.node; ++cur)
        data_allocator::deallocate(*cur, buffer_size());
      start = new_start;
    }
    else {
      copy(last, finish, first);
      iterator new_finish = finish - n;
      destroy(new_finish, finish);
      for (map_pointer cur = new_finish.node + 1; cur <= finish.node; ++cur)
        data_allocator::deallocate(*cur, buffer_size());
      finish = new_finish;
    }
    return start + elems_before;
  }
}
 
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::clear()
{
  // 首先析构除起点和终点的所有元素, 并释放相应空间
  for (map_pointer node = start.node + 1; node < finish.node; ++node) {
    destroy(*node, *node + buffer_size());
    data_allocator::deallocate(*node, buffer_size());
  }
 
  // 如果deque本身不为空, 析构所有对象, 并释放掉结尾的内存
  if (start.node != finish.node) {
    destroy(start.cur, start.last);
    destroy(finish.first, finish.cur);
    data_allocator::deallocate(finish.first, buffer_size());
  }
  // 析构所有元素, 但是不释放空间, 因为deque要满足这个前置条件
  // 具体的细节见本文件开头'特性'
  else
    destroy(start.cur, finish.cur);
 
  finish = start;
}
 
// 创建内部使用的map
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::create_map_and_nodes(size_type num_elements)
{
  // 需要的结点数, 元素个数 / 每个缓冲区能容纳的元素数 + 1
  size_type num_nodes = num_elements / buffer_size() + 1;
 
  // map要维护的结点, 这里最小的值为8, 见initial_map_size()
  map_size = max(initial_map_size(), num_nodes + 2);
  map = map_allocator::allocate(map_size);
 
  // 将[nstart, nfinish)区间设置在map的中间,
  // 这样就能保证前后增长而尽可能减少map的重新分配次数
  map_pointer nstart = map + (map_size - num_nodes) / 2;
  map_pointer nfinish = nstart + num_nodes - 1;
 
  // 分配结点空间
  map_pointer cur;
  __STL_TRY {
    for (cur = nstart; cur <= nfinish; ++cur)
      *cur = allocate_node();
  }
#     ifdef  __STL_USE_EXCEPTIONS
  catch(...) {
    for (map_pointer n = nstart; n < cur; ++n)
      deallocate_node(*n);
    map_allocator::deallocate(map, map_size);
    throw;
  }
#     endif /* __STL_USE_EXCEPTIONS */
 
  // 维护指针状态
  start.set_node(nstart);
  finish.set_node(nfinish);
  start.cur = start.first;
  finish.cur = finish.first + num_elements % buffer_size();
}
 
// This is only used as a cleanup function in catch clauses.
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::destroy_map_and_nodes()
{
  for (map_pointer cur = start.node; cur <= finish.node; ++cur)
    deallocate_node(*cur);
  map_allocator::deallocate(map, map_size);
}
 
// 分配n个结点, 并以value为蓝本初始化
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::fill_initialize(size_type n,
                                               const value_type& value)
{
  create_map_and_nodes(n);
  map_pointer cur;
  __STL_TRY {
    for (cur = start.node; cur < finish.node; ++cur)
      uninitialized_fill(*cur, *cur + buffer_size(), value);
    uninitialized_fill(finish.first, finish.cur, value);
  }
#       ifdef __STL_USE_EXCEPTIONS
  catch(...) {
    for (map_pointer n = start.node; n < cur; ++n)
      destroy(*n, *n + buffer_size());
    destroy_map_and_nodes();
    throw;
  }
#       endif /* __STL_USE_EXCEPTIONS */
}
 
 
#ifdef __STL_MEMBER_TEMPLATES
 
template <class T, class Alloc, size_t BufSize>
template <class InputIterator>
void deque<T, Alloc, BufSize>::range_initialize(InputIterator first,
                                                InputIterator last,
                                                input_iterator_tag) {
  create_map_and_nodes(0);
  for ( ; first != last; ++first)
    push_back(*first);
}
 
template <class T, class Alloc, size_t BufSize>
template <class ForwardIterator>
void deque<T, Alloc, BufSize>::range_initialize(ForwardIterator first,
                                                ForwardIterator last,
                                                forward_iterator_tag) {
  size_type n = 0;
  distance(first, last, n);
  create_map_and_nodes(n);
  __STL_TRY {
    uninitialized_copy(first, last, start);
  }
  __STL_UNWIND(destroy_map_and_nodes());
}
 
#endif /* __STL_MEMBER_TEMPLATES */
 
// 仅当finish.cur == finish.last - 1才调用
// 即最后一个缓冲区没有空间才调用
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::push_back_aux(const value_type& t)
{
  value_type t_copy = t;
  reserve_map_at_back();
  *(finish.node + 1) = allocate_node();
  __STL_TRY {
    construct(finish.cur, t_copy);
    finish.set_node(finish.node + 1);
    finish.cur = finish.first;
  }
  __STL_UNWIND(deallocate_node(*(finish.node + 1)));
}
 
// Called only if start.cur == start.first.
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::push_front_aux(const value_type& t)
{
  value_type t_copy = t;
  reserve_map_at_front();
  *(start.node - 1) = allocate_node();
  __STL_TRY {
    start.set_node(start.node - 1);
    start.cur = start.last - 1;
    construct(start.cur, t_copy);
  }
#     ifdef __STL_USE_EXCEPTIONS
  catch(...) {
    start.set_node(start.node + 1);
    start.cur = start.first;
    deallocate_node(*(start.node - 1));
    throw;
  }
#     endif /* __STL_USE_EXCEPTIONS */
}
 
// Called only if finish.cur == finish.first.
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>:: pop_back_aux()
{
  deallocate_node(finish.first);
  finish.set_node(finish.node - 1);
  finish.cur = finish.last - 1;
  destroy(finish.cur);
}
 
// Called only if start.cur == start.last - 1.  Note that if the deque
//  has at least one element (a necessary precondition for this member
//  function), and if start.cur == start.last, then the deque must have
//  at least two nodes.
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::pop_front_aux()
{
  destroy(start.cur);
  deallocate_node(start.first);
  start.set_node(start.node + 1);
  start.cur = start.first;
}
 
#ifdef __STL_MEMBER_TEMPLATES
 
// 将[first, last)区间元素插入到pos前
 
template <class T, class Alloc, size_t BufSize>
template <class InputIterator>
void deque<T, Alloc, BufSize>::insert(iterator pos,
                                      InputIterator first, InputIterator last,
                                      input_iterator_tag)
{
  // 由于是Input Iterator, 则使用通用的inserter完成插入操作
  copy(first, last, inserter(*this, pos));
}
 
 
template <class T, class Alloc, size_t BufSize>
template <class ForwardIterator>
void deque<T, Alloc, BufSize>::insert(iterator pos,
                                      ForwardIterator first,
                                      ForwardIterator last,
                                      forward_iterator_tag)
{
  size_type n = 0;
  distance(first, last, n);
  if (pos.cur == start.cur) {
    iterator new_start = reserve_elements_at_front(n);
    __STL_TRY {
      uninitialized_copy(first, last, new_start);
      start = new_start;
    }
    __STL_UNWIND(destroy_nodes_at_front(new_start));
  }
  else if (pos.cur == finish.cur) {
    iterator new_finish = reserve_elements_at_back(n);
    __STL_TRY {
      uninitialized_copy(first, last, finish);
      finish = new_finish;
    }
    __STL_UNWIND(destroy_nodes_at_back(new_finish));
  }
  else
    insert_aux(pos, first, last, n);
}
 
#endif /* __STL_MEMBER_TEMPLATES */
 
 
// 在指定位置前插入元素
 
//              insert_aux(iterator pos, const value_type& x)
//                                   |
//                                   |----------- 判断pos前端元素少还是后端元素少
//                                   |
//               -----------------------------------------------
//         前端少 |                                       后端少 |
//               |                                             |
//               ↓                                             |
//           进行相关操作                                   进行相关操作
 
// 下面以pos前面元素少的情形进行说明, 为了简化, 假设操作不会超过一个缓冲区区间
//
// 插入前状态
//           start            pos                                 end
//             ↓               ↓                                   ↓
// ---------------------------------------------------------------------
// |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   | X |
// ---------------------------------------------------------------------
//
// 需要进行操作的区间
//                需要拷贝的区间
//                 -------------
//       start     |           |                                  end
//         ↓       ↓           ↓                                   ↓
// ---------------------------------------------------------------------
// |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   | X |
// ---------------------------------------------------------------------
//             ↑   ↑       ↑   ↑
//        front1   |       |   |
//                 |       |   |
//            front2       |   |
//                         |   |
//                       pos   |
//                             |
//                          pos1
// 拷贝操作完成后
//
//         这是[front2, pos1)
//             ------------- --------- 这里是给待插入元素预留的空间
//       start |           | |                                    end
//         ↓   ↓           ↓ ↓                                     ↓
// ---------------------------------------------------------------------
// |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   | X |
// ---------------------------------------------------------------------
//         ↑
//   这里存储的是原来的front()
//
 
 
template <class T, class Alloc, size_t BufSize>
typename deque<T, Alloc, BufSize>::iterator
deque<T, Alloc, BufSize>::insert_aux(iterator pos, const value_type& x)
{
  difference_type index = pos - start;
  value_type x_copy = x;
 
  // 前面的时候用的移位操作, 这里怎么不用了呢^_^?
  if (index < size() / 2) {
    push_front(front());
    iterator front1 = start;
    ++front1;
    iterator front2 = front1;
    ++front2;
    pos = start + index;
    iterator pos1 = pos;
    ++pos1;
    copy(front2, pos1, front1);
  }
  else {
    push_back(back());
    iterator back1 = finish;
    --back1;
    iterator back2 = back1;
    --back2;
    pos = start + index;
    copy_backward(pos, back2, back1);
  }
  *pos = x_copy;
  return pos;
}
 
 
// 在pos前插入n个值为x的元素
 
//         insert_aux(iterator pos, size_type n, const value_type& x)
//                                   ↓
//                      elems_before = pos - start;
//                            length = size();
//                                   |
//                                   |---------- elems_before < length / 2 ?
//                                   |           判断哪侧元素少, 就对哪侧进行操作
//               ---------------------------------------
//           Yes |                                     |  No
//               |                                     |
//               ↓                                     ↓
// reserve_elements_at_front(n);          reserve_elements_at_back(n);
// 根据具体情况进行元素的拷贝操作             根据具体情况进行元素的拷贝操作
 
 
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
                                          size_type n, const value_type& x)
{
  const difference_type elems_before = pos - start;
  size_type length = size();
  value_type x_copy = x;
  if (elems_before < length / 2) {
    iterator new_start = reserve_elements_at_front(n);
    iterator old_start = start;
    pos = start + elems_before;
    __STL_TRY {
      if (elems_before >= difference_type(n)) {
        iterator start_n = start + difference_type(n);
        uninitialized_copy(start, start_n, new_start);
        start = new_start;
        copy(start_n, pos, old_start);
        fill(pos - difference_type(n), pos, x_copy);
      }
      else {
        __uninitialized_copy_fill(start, pos, new_start, start, x_copy);
        start = new_start;
        fill(old_start, pos, x_copy);
      }
    }
    __STL_UNWIND(destroy_nodes_at_front(new_start));
  }
  else {
    iterator new_finish = reserve_elements_at_back(n);
    iterator old_finish = finish;
    const difference_type elems_after = difference_type(length) - elems_before;
    pos = finish - elems_after;
    __STL_TRY {
      if (elems_after > difference_type(n)) {
        iterator finish_n = finish - difference_type(n);
        uninitialized_copy(finish_n, finish, finish);
        finish = new_finish;
        copy_backward(pos, finish_n, old_finish);
        fill(pos, pos + difference_type(n), x_copy);
      }
      else {
        __uninitialized_fill_copy(finish, pos + difference_type(n),
                                  x_copy,
                                  pos, finish);
        finish = new_finish;
        fill(pos, old_finish, x_copy);
      }
    }
    __STL_UNWIND(destroy_nodes_at_back(new_finish));
  }
}
 
#ifdef __STL_MEMBER_TEMPLATES
 
// 供给insert(iterator pos, ForwardIterator first, ForwardIterator last,)
// 处理通用情况
template <class T, class Alloc, size_t BufSize>
template <class ForwardIterator>
void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
                                          ForwardIterator first,
                                          ForwardIterator last,
                                          size_type n)
{
  const difference_type elems_before = pos - start;
  size_type length = size();
  if (elems_before < length / 2) {
    iterator new_start = reserve_elements_at_front(n);
    iterator old_start = start;
    pos = start + elems_before;
    __STL_TRY {
      if (elems_before >= difference_type(n)) {
        iterator start_n = start + difference_type(n);
        uninitialized_copy(start, start_n, new_start);
        start = new_start;
        copy(start_n, pos, old_start);
        copy(first, last, pos - difference_type(n));
      }
      else {
        ForwardIterator mid = first;
        advance(mid, difference_type(n) - elems_before);
        __uninitialized_copy_copy(start, pos, first, mid, new_start);
        start = new_start;
        copy(mid, last, old_start);
      }
    }
    __STL_UNWIND(destroy_nodes_at_front(new_start));
  }
  else {
    iterator new_finish = reserve_elements_at_back(n);
    iterator old_finish = finish;
    const difference_type elems_after = difference_type(length) - elems_before;
    pos = finish - elems_after;
    __STL_TRY {
      if (elems_after > difference_type(n)) {
        iterator finish_n = finish - difference_type(n);
        uninitialized_copy(finish_n, finish, finish);
        finish = new_finish;
        copy_backward(pos, finish_n, old_finish);
        copy(first, last, pos);
      }
      else {
        ForwardIterator mid = first;
        advance(mid, elems_after);
        __uninitialized_copy_copy(mid, last, pos, finish, finish);
        finish = new_finish;
        copy(first, mid, pos);
      }
    }
    __STL_UNWIND(destroy_nodes_at_back(new_finish));
  }
}
 
#else /* __STL_MEMBER_TEMPLATES */
 
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
                                          const value_type* first,
                                          const value_type* last,
                                          size_type n)
{
  const difference_type elems_before = pos - start;
  size_type length = size();
  if (elems_before < length / 2) {
    iterator new_start = reserve_elements_at_front(n);
    iterator old_start = start;
    pos = start + elems_before;
    __STL_TRY {
      if (elems_before >= difference_type(n)) {
        iterator start_n = start + difference_type(n);
        uninitialized_copy(start, start_n, new_start);
        start = new_start;
        copy(start_n, pos, old_start);
        copy(first, last, pos - difference_type(n));
      }
      else {
        const value_type* mid = first + (difference_type(n) - elems_before);
        __uninitialized_copy_copy(start, pos, first, mid, new_start);
        start = new_start;
        copy(mid, last, old_start);
      }
    }
    __STL_UNWIND(destroy_nodes_at_front(new_start));
  }
  else {
    iterator new_finish = reserve_elements_at_back(n);
    iterator old_finish = finish;
    const difference_type elems_after = difference_type(length) - elems_before;
    pos = finish - elems_after;
    __STL_TRY {
      if (elems_after > difference_type(n)) {
        iterator finish_n = finish - difference_type(n);
        uninitialized_copy(finish_n, finish, finish);
        finish = new_finish;
        copy_backward(pos, finish_n, old_finish);
        copy(first, last, pos);
      }
      else {
        const value_type* mid = first + elems_after;
        __uninitialized_copy_copy(mid, last, pos, finish, finish);
        finish = new_finish;
        copy(first, mid, pos);
      }
    }
    __STL_UNWIND(destroy_nodes_at_back(new_finish));
  }
}
 
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::insert_aux(iterator pos,
                                          const_iterator first,
                                          const_iterator last,
                                          size_type n)
{
  const difference_type elems_before = pos - start;
  size_type length = size();
  if (elems_before < length / 2) {
    iterator new_start = reserve_elements_at_front(n);
    iterator old_start = start;
    pos = start + elems_before;
    __STL_TRY {
      if (elems_before >= n) {
        iterator start_n = start + n;
        uninitialized_copy(start, start_n, new_start);
        start = new_start;
        copy(start_n, pos, old_start);
        copy(first, last, pos - difference_type(n));
      }
      else {
        const_iterator mid = first + (n - elems_before);
        __uninitialized_copy_copy(start, pos, first, mid, new_start);
        start = new_start;
        copy(mid, last, old_start);
      }
    }
    __STL_UNWIND(destroy_nodes_at_front(new_start));
  }
  else {
    iterator new_finish = reserve_elements_at_back(n);
    iterator old_finish = finish;
    const difference_type elems_after = length - elems_before;
    pos = finish - elems_after;
    __STL_TRY {
      if (elems_after > n) {
        iterator finish_n = finish - difference_type(n);
        uninitialized_copy(finish_n, finish, finish);
        finish = new_finish;
        copy_backward(pos, finish_n, old_finish);
        copy(first, last, pos);
      }
      else {
        const_iterator mid = first + elems_after;
        __uninitialized_copy_copy(mid, last, pos, finish, finish);
        finish = new_finish;
        copy(first, mid, pos);
      }
    }
    __STL_UNWIND(destroy_nodes_at_back(new_finish));
  }
}
 
#endif /* __STL_MEMBER_TEMPLATES */
 
// 在deque前端分配新结点
template <class T, class Alloc, size_t BufSize>
void deque<T, Alloc, BufSize>::new_elements_at_front(size_type new_elements)
{
  size_type new_nodes = (new_elements + buffer_size() - 1) / buffer_size();
  reserve_map_at_front(new_nodes);
  size_type i;
  __STL_TRY {
    for (i = 1; i <= new_nodes; ++i)
      *(start.node - i) = allocate_node();
  }
#       ifdef __STL_USE_EXCEPTIONS
  catch(...) {
    for (size_type j = 1; j < i; ++j)
      deallocate_node(*(start.node - j));
    throw;
  }
#       endif /* __STL_USE_EXCEPTIONS */
}

deque和vector的不同之处:

1、两端都能够快速插入和删除元素。vector只能在尾端进行。

2、deque的元素存取和迭代器操作会稍微慢一些。因为deque的内部结构会多一个间接过程。

3、迭代器是特殊的智能指针,而不是一般指针。它需要在不同的区块之间跳转。

4、deque可以包含更多的元素,其max_size可能更大。因为不止使用一块内存。

5、不支持对容量和内存分配时机的控制。

注意:在除了首尾两端的其他地方插入和删除元素,都将会导致指向deque元素的任何pointers、references、iterators失效。不过,deque的内存重分配优于vector。因为其内部结构显示不需要复制所有元素。

6、deque的内存区块不再被使用时,会被释放。deque的内存大小是可缩减的。不过,是不是这么做以及怎么做由实作版本定义。

deque和vector相似的特性:

1、在中间部分插入和删除元素相对较慢,因为所有元素都要被移动。

2、迭代器属于随即存取迭代器。

最好采用deque的情形:

1、需要在两端插入和删除元素。

2、无需引用容器内的元素。

3、要求容器释放不再使用的元素。

示例:

// deque.cpp : 定义控制台应用程序的入口点。

//

#include "stdafx.h"

#include<iostream>

#include<deque>

usingnamespacestd;

int_tmain(intargc, _TCHAR*argv[])

{

deque<int>d;

d.push_back( 10 );

d.push_back(20);

d.push_back(30);

cout<<"原始双端队列:"<<endl;

for(inti=0; i<d.size(); i++)

{

cout<<d.at(i)<<"\t";

}

cout<<endl;

d.push_front(5);

d.push_front(3);

d.push_front(1);

cout<<"after push_front(5.3.1):"<<endl;

for(inti=0;i<d.size();i++)

{

cout<<d.at(i)<<"\t";

}

cout<<endl;

d.pop_front();

d.pop_front();

cout<<"after pop_front() two times:"<<endl;

for(inti=0;i<d.size();i++)

{

cout<<d.at(i)<<"\t";

}

cout<<endl;

return0;

}

/* 6个常用函数

front()、back()、push()、pop()、empty()、size()

*/

#include <stdio.h>

#include <queue>

using namespace std;

int main()

{

int n, m, size;

queue <int> q;//定义队列q

q.push(1);

q.push(2);//将1 、2压入队列

while (!q.empty())//判断队列是否为空

{

n = q.front();//返回队列头部数据

m = q.back();//返回队列尾部数据

size = q.size();//返回队列里的数据个数

q.pop();//队列头部数据出队

printf("%d %d %d\n", n, m, size);

}

return 0;

}

源码分析完毕。

• 队列是一种先进先出的数据结构(First In Fist Out ,FIFO)。

• 它有两个出口,queue 允许新增元素、移除元素、从最底端加入元素、 取得最顶端元素。

• 但除了最底端可以加入、最顶端可以取出外, 没有任何其它方法可以 存取队列的其它元素。

• 队列就像一个两端相通的水管,只允许一端插入,另一端取出,取出 的球就不在水管里面了,先放入管中的球就会先从管中拿出

换言之, queue 队列不允许有遍历行为。

将元素推入queue 队列的操 作称为push, 将元素推出queue 队列的操作称为pop。

queue所有元素的进出都必须符合“先进后出”的条件,只有queue顶端的 元素, 才有机会被外界取用。

queue不提供遍历功能,也不提供迭代器

queue是一种配接器(Adapter):STL queue往往不被归类为container (容器),而被归类为container adapter,STL中队列是以双端队列作为 缺省情况下实现的,而这种具有“修改某物接口,形成另一种风貌”性质, 称为adapter(配接器)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值