STL

STL解析 —— priority_queue

Standard Template Library —— priority_queue

ZingLix May 29, 2018

优先队列(priority queue)是一种队列,但是每次弹出的是优先级最高的元素,优先级可以有不同表现,比如在最小堆中是值最小的元素,而在最大堆中则是值最大的元素。关于其数据结构本身已有过详细讨论

STL 中的优先队列

1
2
3
4
5
template<
    class T,
    class Container = std::vector<T>,
    class Compare = std::less<typename Container::value_type>
> class priority_queue;

以上是优先队列的声明。分别表示:

  • T:所存储的数据类型
  • Container:用于存储二叉堆的容器,默认是 vector
  • Compare:比较函数,默认是小于

STL 中的优先队列与通常一样,利用二叉堆来实现,内存结构为数组。又出于数组不可增长,所以采用 vector 作为默认底层容器。若要替换,则容器必须为顺序容器,且具有如下函数:

  • front
  • push_back
  • pop_back

在 STL 中,除 vector 外,只有 deque 满足此要求。而因为是借由其他容器加以封装而实现的,所以 priority_queue 被分类至 容器适配器

函数实现

虽然说是二叉堆,但在实现中并不自己维护堆性质,而是调用 <algorithm> 中提供的heap算法,从而使实现变得极为便捷。

top

返回顶元素的引用。返回容器中第一个元素即可。

1
const_reference top() const { return c.front(); }

push

将一个元素加入到队列中。将其插入到容器末尾,然后调用push_heap即可。

1
2
3
4
void push(const value_type& value) {
    c.push_back(value);
    push_heap(c.begin(), c.end(), comp);
}

pop

移除顶元素。pop_heap会将顶元素移到容器末尾,并不删除,所以需要对容器pop_back

1
2
3
4
void pop() {
    pop_heap(c.begin(), c.end(), comp);
    c.pop_back();
}

emplace

构造一个新元素并插入到队列中。与 push 类似。

1
2
3
4
5
template< class... Args >
void emplace(Args&&... args) {
    c.emplace_back(std::forward<Args>(args)...);
    push_heap(c.begin(), c.end(), comp);
}

empty & size

返回队列是否为空和大小。底层容器都具有相关的函数。

1
2
bool empty() { return c.empty(); }
size_type size() const { return c.size(); }