简述
priority_queue(优先队列)是容器适配器,它提供常数时间的(默认)最大元素查找,对数代价的插入与释出。可用用户提供的 Compare
更改顺序,例如,用 std::greater<T> 将导致最小元素作为 top()出现。用 priority_queue
工作类似管理某些随机访问容器中的堆,优势是不可能突然把堆非法化。
简单来说priority_queue就是STL提供的一种利用堆排序(Heap Sort)的容器,这样我们以后用优先队列就不用再敲一遍堆排序了,关于堆排序的实现请参照另一篇博文【Algorithms】堆排序(Heap Sort)。
使用方法
那么知道了这个工具后我们怎么使用呢,接下来就是这个工具的使用说明书了~
首先我们要使用一个函数,需要添加函数所在的头文件,#include<queue>便是priority_queue的头文件。
接下来我们应该定义一个priority_queue对象,它在c++中的声明如下:
template<
class T,
class Container = std::vector<T>,
class Compare = std::less<typename Container::value_type>
> class priority_queue;
priority_queue<Class T> q; // 一般的构造方法,其中T为队列中存储的元素类型
在运用它之前还有一个工作要做,那就是学习如何操纵它,priority_queue常用函数如下表
元素访问 | 功能 |
top() | 访问堆顶元素,返回优先级最大的元素即堆顶元素 |
容量 | |
empty() | 判断堆是否为空,如果为空返回true |
size() | 返回堆内剩余元素个数 |
修改器 | |
push() | 向优先队列后面添加一个元素,并对底层元素排序(保持优先队列) |
pop() | 将堆顶元素出队,并对底层元素排序 |
swap(priority_queue) | 交换两个优先队列内的全部元素(要求两个队列类型、大小全部相同) |
emplace() | 向优先队列顶部插入一个元素,并对底层元素排序 |
注:emplace()VS push()
当我们使用push()时,我们创建一个对象,然后将其插入priority_queue。使用emplace(),对象就地构造并保存不必要的副本。
代码示例:
#include<iostream>
#include<queue>
using namespace std;
int x[10]={1,5,7,9,6,3,8,4,2,0};
int main()
{
priority_queue<int> q;
for(int i=0;i<10;i++){
q.push(x[i]);
}
while(!q.empty()){
cout<<q.top()<<" ";
q.pop();
}
return 0;
}
Output:
9 8 7 6 5 4 3 2 1 0
但是我们会发现,使用默认的优先队列,只能实现最大堆,这是因为优先队列默认的比较小于,也就是说堆的下移操作是基于小于号的,比较小的元素会放到下面,自然最大的元素就拍到堆顶啦d=====( ̄▽ ̄*)b,那么我们能不能实现小根优先队列呢?答案是肯定的,通过下面的语句对()运算符进行重载实现了大于比较的功能,因此也就可以实现最小优先队列啦
priority_queue<int, vector<int>, greater<int> > p;
#include<iostream>
#include<queue>
using namespace std;
int x[10]={1,5,7,9,6,3,8,4,2,0};
int main()
{
priority_queue<int,vector<int>,greater<int> > q;
for(int i=0;i<10;i++){
q.push(x[i]);
}
while(!q.empty()){
cout<<q.top()<<" ";
q.pop();
}
return 0;
}
Output:
0 1 2 3 4 5 6 7 8 9
当然优先队列的用法不仅仅如此,还可以向队列中放入自定义类型,比如struct
#include<iostream>
#include<queue>
using namespace std;
typedef struct que
{
int a,b;
que(int x1,int x2){ //这里重载了que构造函数
a=x1,b=x2;
}
friend bool operator< (que q1,que q2){ // 对运算符‘<’进行重载,不然无法进行排序,因为
return q1.a > q2.a; // c++内部的‘<’没有比较结构体的功能。
} // 并且注意这里要定义为友元,不然编译通不过
}; // 注:这里是通过重载小于号实现的最小优先队列哦
int main()
{
int a,b;
priority_queue<que> q; // que类型的优先队列
for(int i=0;i<10;i++){
cin>>a>>b;
q.push(que(a,b));
}
while(!q.empty()){
cout<<"a "<<q.top().a<<" b "<<q.top().b<<endl;;
q.pop();
}
return 0;
}
Input: Output:
1 9 a 0 b 0
2 8 a 1 b 9
3 7 a 2 b 8
4 6 a 3 b 7
5 5 a 4 b 6
6 4 a 5 b 5
7 3 a 6 b 4
8 2 a 7 b 3
9 1 a 8 B 2
0 0 a 9 b 1