【STL】Deques

Deques(雙端隊列)

雙端隊列是指允許兩端都可以進行入隊和出隊操作的隊列,其元素的邏輯結構仍是線性結構。將隊列的兩端分別稱爲前端和後端,兩端都可以入隊和出隊。
deque同vector一樣也是順序容器。它內部擁有更復雜的數據結構,從deque隊列的兩端插入和刪除元素都很快,在容器中間插入或刪除就沒有那麼的高的效率了,如果你想要隨機讀取數組元素還是選擇vector。

基本操作:

插入:雙端隊列不僅提供了push_back成員函數,還提供了push_front成員函數,從而可以在序列的前後兩端進行插入操作。對於雙端隊列,在序列的兩端插入元素的時間複雜度均爲常數,在中間插入元素的時間複雜度與插入點到最近序列端點的距離成正比。並且,對於雙端隊列的插入操作(包括在雙端插入和中間插入),將會使所有的迭代器失效,只能採用下標操作。

刪除:雙端隊列不僅提供了pop_back成員函數,還提供了pop_front成員函數,從而可以在序列的前後兩端進行刪除操作。在中間的刪除操作將會使所有迭代器失效;而在兩端的刪除操作,僅當刪除位置就是迭代器所指向位置時會使迭代器失效。

從頭部插入元素,不會增加新元素,只將原來有的元素覆蓋。

操作實例

deque<int> d;
    for (int i = 1; i < 10; i++)
        d.push_back(i);

    d.pop_front();
    d.pop_front();

    std::deque<int>::iterator pit;
    for (pit = d.begin(); pit != d.end(); pit++)
        cout << *pit << " ";
    cout << endl;

    d.pop_back();
    for (pit = d.begin(); pit != d.end(); pit++)
        cout << *pit << " ";
    cout << endl;

    d.erase(d.begin() + 1);
    for (pit = d.begin(); pit != d.end(); pit++)
        cout << *pit << " ";
    cout << endl;

    d.clear();
    cout << d.size() << endl;

這裏寫圖片描述

deques源碼

//stl_deque.h 
// 如果vector能滿足你的需求, 那麼就使用vector
// 如果不得不使用deque, 那麼在進行一算法(尤其是sort)操作時
// 應該先把deque中的元素複製到vector中
// 執行完算法再複製回去
// 這樣的效率往往要高於直接使用算法的效率

#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;      // 此迭代器所指之緩衝區的尾(含備用空間)
  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
//從外界看上去維護的是一段連續空間的關鍵
////////////////////////////////
  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個距離
  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);
  }

  /*
  迭代器內對各種指針運算都進行了重載,
  所以各種指針運算如加、減、前進、後退等都不能直觀視之。
  最關鍵的是:一旦遇到緩衝區邊緣,要特別小心,
  視前進或後退而定,可能需要調用set_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;
  }
  //以下調用__deque_iterator<>::operator*
  const_reference front() const { return *start; }
  const_reference back() const {
    const_iterator tmp = finish;
    --tmp; //調用__deque_iterator<>::operator--
    return *tmp; //調用__deque_iterator<>::operator*
  }

  // 當前容器擁有的元素個數, 調用迭代器重載的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();  //進行緩衝區的釋放
  }

  //與pop_back()類似
  void pop_front() {
    if (start.cur != start.last - 1)
    {
      destroy(start.cur);
      ++start.cur;
    }
    else
      pop_front_aux();
  }

public:                         // Insert

/////////////////////////
// 在指定位置前插入元素
/////////////////////////
  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
  void reserve_map_at_back (size_type nodes_to_add = 1)
  {
    if (nodes_to_add + 1 > map_size - (finish.node - map))
        //如果map尾端的節點備用空間不夠
        //符合以上條件則必須重換一個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)
        //如果map前端的節點備用空間不夠
        //符合以上條件則必須重換一個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的元素
////////////////////////////////
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)區間的元素
//////////////////////////////
template <class T, class Alloc, size_t BufSize>
deque<T, Alloc, BufSize>::iterator
deque<T, Alloc, BufSize>::erase(iterator first, iterator last)
{
    //清楚的是整個deque,直接調用clear()
  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;  //標記deque新起點
      destroy(start, new_start); //移動完畢,將冗餘元素析構
      //將冗餘緩衝區釋放
      for (map_pointer cur = start.node; cur < new_start.node; ++cur)
        data_allocator::deallocate(*cur, buffer_size());
      start = new_start;  //設定deque新起點
    }
    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;
  }
}

//該函數清除整個deque,deque初始狀態(無任何元素)時,有一個
//緩衝區,因此clear後恢復初始,要保留一個緩衝區
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());
  }

  // 至少有頭尾兩個緩衝區
  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,負責安排產生並安排好deque的結構
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()
  //最大爲“所需節點數加2”,前後各預備一個,擴充時可用
  map_size = max(initial_map_size(), num_nodes + 2);
  //配置有map_size個節點的map
  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 {
      //爲map內的每個現用節點配置緩衝區。所有緩衝區加起來就是deque
      //的可用空間(最後一個緩衝區可能留有一些富裕)
    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 */

  // 維護指針狀態,爲deque的兩個迭代器start、end設置正確內容
  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爲藍本初始化
該函數負責產生並安排好deque的結構
併爲元素設置初值
*/
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); //把deque的結構都產生並安排好
  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(); //若符合某種條件則必須重換一個map
  *(finish.node + 1) = allocate_node(); //配置一個新節點(緩衝區)
  __STL_TRY {
    construct(finish.cur, t_copy);
    finish.set_node(finish.node + 1); //改變finish,令其指向新緩衝區
    finish.cur = finish.first; //設定finish的狀態
  }
  __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(); //若符合某條件則必須重換一個map
  __STL_TRY {
    start.set_node(start.node - 1); //配置一個新緩衝區
    start.cur = start.last - 1;
    construct(start.cur, t_copy);
  }
#     ifdef __STL_USE_EXCEPTIONS
  catch(...) {  //commit or rollback:若非全部成功,就一個不留
    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的狀態,指向
  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.
//與上邊pop_back_aux()相似
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 */

//////////////////////
// 在指定位置前插入元素
//////////////////////
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章