Post

C++ STL Container Adapter Queue

C++ STL Container Adapter Queue

Queue

  • based on gnu 2.9
  • 底层支撑的Sequence可以为deque, list

Achieve

queue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
    typedef typename Sequence::value_type value_type;
    typedef typename Sequence::size_type size_type;
    typedef typename Sequence::reference reference;
    typedef typename Sequence::const_reference const_reference;
*/
template <class T, class Sequence = deque<T> >
class queue {
    Sequence c;
    // 调用Sequence的函数实现
    bool empty() const { return c.empty(); }
    size_type size() const { return c.size(); }
    reference front() { return c.front(); }
    const_reference front() const { return c.front(); }
    reference back() { return c.back(); }
    const_reference back() const { return c.back(); }
    void push(const value_type& x) { c.push_back(x); }
    void pop() { c.pop_front(); }
};

priority_queue

  • 底层用可以实现heap操作的容器支持
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
    /*
      typedef typename Sequence::value_type value_type;
      typedef typename Sequence::size_type size_type;
      typedef typename Sequence::reference reference;
      typedef typename Sequence::const_reference const_reference;
    */
    template <class T, class Sequence = vector<T>, 
            class Compare = less<typename Sequence::value_type> >
    class  priority_queue {
      Sequence c;
      Compare comp;
    
      priority_queue(const value_type* first, const value_type* last, 
                      const Compare& x) : c(first, last), comp(x) {
          make_heap(c.begin(), c.end(), comp);
      }
    
      bool empty() const { return c.empty(); }
      size_type size() const { return c.size(); }
      const_reference top() const { return c.front(); }
        
      void push(const value_type& x) {
          try {
              c.push_back(x); 
              push_heap(c.begin(), c.end(), comp);
          }
      }
    
      void pop() {
          try {
              pop_heap(c.begin(), c.end(), comp);
              c.pop_back();
          }
      }
    }
    

heap

  • heap不是一个容器, 只是规定了容器的操作方式

    make_heap

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    
    template <class RandomAccessIterator, class Compare, class T, class Distance>
    void __make_heap(RandomAccessIterator first, RandomAccessIterator last,
                   Compare comp, T*, Distance*) {
      // 只有一个元素
      if (last - first < 2) return;
      Distance len = last - first;
      Distance parent = (len - 2)/2;
        
      while (true) {
          __adjust_heap(first, parent, len, T(*(first + parent)), comp);
          if (parent == 0) return;
          parent--;
      }
    }
    

adjust_heap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <class RandomAccessIterator, class Distance, class T, class Compare>
void __adjust_heap(RandomAccessIterator first, Distance holeIndex, Distance len, T value, Compare comp) {
    Distance topIndex = holeIndex;
    Distance secondChild = 2 * holeIndex + 2;
    // 先将所有child往上放
    while (secondChild < len) {
        if (comp(*(first + secondChild), *(first + (secondChild - 1))))
            secondChild--;
        *(first + holeIndex) = *(first + secondChild);
        holeIndex = secondChild;
        secondChild = 2 * (secondChild + 1);
    }
    // 边界处理, 只有一个child
    if (secondChild == len) {
        *(first + holeIndex) = *(first + (secondChild - 1));
        holeIndex = secondChild - 1;
    }
    // 最后将要调整的值重现插入回heap
    __push_heap(first, holeIndex, topIndex, value, comp);
}

push_heap

1
2
3
4
5
6
7
8
9
10
11
template <class RandomAccessIterator, class Distance, class T, class Compare>
void __push_heap(RandomAccessIterator first, Distance holeIndex, Distance topIndex, T value, Compare comp) {
    Distance parent = (holeIndex - 1) / 2;
    // 如果不是要插入的位置, 往上找
    while (holeIndex > topIndex && comp(*(first + parent), value)) {
        *(first + holeIndex) = *(first + parent);
        holeIndex = parent;
        parent = (holeIndex - 1) / 2;
    }
    *(first + holeIndex) = value;
}

pop_heap

1
2
3
4
5
template <class RandomAccessIterator, class T, class Compare, class Distance>
inline void __pop_heap(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator result, T value, Compare comp, Distance*) {
    *result = *first;
    __adjust_heap(first, Distance(0), Distance(last - first), value, comp);
}
This post is licensed under CC BY 4.0 by the author.