优先级队列priority_queue()是STL中的一种容器适配器,需导入#include<queue>以使用。它具备以下特点:
- 一端进一端出
- 非先进先出的规则,而是按照优先级来排序,每次取出队列中优先级最大的元素
1.priority_queue()定义
template <typename T,
typename Container=vector<T>,
typename Compare=less<T> >
class priority_queue{
//......
}
T:队列中存储的元素类型
Container:底层容器。默认为vector<T>,还可以用deque结构作为底层容器。
Compare:排序规则。默认为less<T>,即降序排序。还可以取greater<T>升序排序。
2.priority_queue() 模板详解(底层实现)
源码:
priority_queue()是一种容器适配器,也就意味着它“不生产代码,只是代码的搬运工”。priority_queue()的构造函数及其方法的底层实现均为堆结构。根据排序规则会构造大顶堆或小顶堆,关于堆的内容见:大顶堆、小顶堆与堆排序_Kallou的博客-CSDN博客
注意,底层实现是堆结构和底层容器是vector并不冲突,vector抑或deque都只是装着数据的容器,而堆是一种数据结构,其规定了容器中数据排列的规则。
3.创建priority_queue()
- 创建空priority_queue()
//默认以vector为底层容器,less为排序规则
priority_queue<int> values;
//指定deque为底层容器,greater为排序规则
priority_queue<int,deque<int>,greater<T>> values;
- 调用构造函数初始化
priority_queue()构造函数要求输入两个迭代器,将两个迭代器所指范围内的元素插入优先级队列中。
//使用普通数组
int values[]{4,1,3,2};
priority_queue<int>copy_values(values,values+4);//{4,2,3,1}
//使用序列式容器
array<int,4>values{ 4,1,3,2 };
priority_queue<int>copy_values(values.begin(),values.end());//{4,2,3,1}
4.自定义排序规则
priority_queue()中的排序规则less和greater有时不能满足需求,开发者可以根据需要自定义排序规则。为了方便理解,先给出less的底层实现源码:
template <typename T>
struct less {
//定义新的排序规则
bool operator()(const T &_lhs, const T &_rhs) const {
return _lhs < _rhs;
}
};
可以看到less就是重载了operator()从而实现越小优先级越高的规则。如果了解堆的构造就知道,往一个有序堆中插入数据需要不断与父节点比较,如果比父节点的优先级更大就会与父节点交换,优先级也就增加了。我没有去看make_heap源码,猜测在make_heap中应该是调用compare类的对象并以括号二元比较的方式获取优先级,重载的括号就作用在此处。
因此,我们可以通过重载()运算符,将其构造成一个模板类作为priority_queue()的compare参数输入达到自定义排序规则的目的:
#include<iostream>
#include<queue>
using namespace std;
//函数对象类
template <typename T>
class cmp
{
public:
//重载 () 运算符
bool operator()(T a, T b)
{
return a > b;
}
};
int main()
{
int a[] = { 4,2,3,5,6 };
priority_queue<int,vector<int>,cmp<int> > pq(a,a+5);
while (!pq.empty())
{
cout << pq.top() << " ";
pq.pop();
}
return 0;
}
运行结果:
2 3 4 5 6
重载operator()需要输入两个参数a和b,返回bool值,意思是b是否比a的优先级高,是则返回1.