一、介绍
priority_queue
是一种队列,其中每个元素都被赋予一个优先级。在优先级队列中,元素以优先级顺序出队,而不是按插入顺序出队。也就是说,优先级最高的元素最先出队。
priority_queue
的声明在<queue>中。
- 从上可以看到,
priority_queue
和stack
、queue
都是容器适配器,且priority_queue
的底层默认容器是vector。 priority_queue
的第三个模板参数class Compare = less<...>
是一个仿函数。在C++中,仿函数是一种类,它重载了函数调用运算符operator()
,从而使得它的对象可以像函数一样被调用。除此之外,仿函数还可以携带状态(即成员变量),这使得它比普通的函数指针更为灵活。
那说了这么多,优先级队列到底是个什么东西,其实它就是我们在c语言数据结构阶段学习的堆(Heap),默认情况下是最大堆。既然是堆,那插入和删除操作的时间复杂度都为O(logn)。
二、接口
priority_queue
是一个模板类,提供了以下接口:
- 构造函数:可以用默认构造函数、带比较器的构造函数、用一对迭代器初始化的构造函数等。
- 成员函数:
push(const value_type& val)
:插入元素。
pop()
:移除优先级最高的元素。
top()
:返回优先级最高的元素。
empty()
:检查队列是否为空。
size()
:返回队列中的元素数量。
以下是一个使用priority_queue
的示例:
#include <iostream>
#include <queue>
#include <vector>
int main() {
// 创建一个最小堆
std::priority_queue<int, std::deque<int>, std::greater<int>> min_pq;
// 插入元素
min_pq.push(10);
min_pq.push(30);
min_pq.push(20);
min_pq.push(5);
min_pq.push(1);
// 输出并移除优先级最高的元素
std::cout << "按优先级顺序排列的元素: ";
while (!min_pq.empty()) {
std::cout << min_pq.top() << " ";
min_pq.pop();
}
std::cout << std::endl;
return 0;
输出:
按优先级顺序排列的元素 (min-heap): 1 5 10 20 30
priority_queue
的底层容器需要支持随机访问迭代器以及上面的那些接口,因此vector
和duque
都能满足这些需求。
三、priority_queue的简单模拟实现
priority_queue
的底层结构就是堆,因此此处只需对对进行通用的封装即可。
template<class T>
class less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
template<class T>
class greater
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
template <class T, class Container = vector<T>, class Compare = less<T> >
class priority_queue
{
public:
void AdjustUp(int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (_comp(_c[parent], _c[child]))
{
swap(_c[parent], _c[child]);
child = parent;
parent = (child - 1) / 2;
}
else
break;
}
}
void AdjustDown(int parent)
{
int child = parent * 2 + 1;
while (child < _c.size())
{
if (child + 1 < _c.size() && _comp(_c[child], _c[child + 1]))
{
child = child + 1;
}
if (_comp(_c[parent], _c[child]))
{
swap(_c[parent], _c[child]);
parent = child;
child = parent * 2 + 1;
}
else
break;
}
}
priority_queue() // 空构造
: _c()
{}
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last) // 用迭代器区间构造
{
while (first != last)
{
_c.push_back(*first);
AdjustUp(_c.size() - 1);
++first;
}
}
bool empty() const
{
return _c.empty();
}
size_t size() const
{
return _c.size();
}
const T& top() const
{
return _c.front();
}
void push(const T& x)
{
_c.push_back(x);
AdjustUp(_c.size() - 1);
}
void pop()
{
swap(_c[0], _c[_c.size() - 1]);
_c.pop_back();
AdjustDown(0);
}
private:
Container _c;
Compare _comp;
};