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.