priority_queue又称为优先队列,其底层是用堆来进行实现的。在优先队列中,队首元素一定是当
前队列中优先级最高的那一个。例如在队列有如下元素,且定义好了优先级:
桃子(优先级3)
梨子(优先级4)
苹果(优先级1)
那么出队的顺序为梨子(4)→桃子(3)→苹果(1)。
当然,可以在任何时候往优先队列里面加入(push)元素,而优先队列底层的数据结构堆(heap)会随
时调整结构,使得每次的队首元素都是优先级最大的。
关于这里的优先级则是规定出来的。例如上面的例子中,也可以规定数字越小的优先级越大。
要使用优先队列,应先添加头文件#include
std;”。
定义的写法和其他STL容器相同, typename可以是任意基本数据类型或容器:
priority_queue name;
和队列不一样的是,优先队列没有front()函数与 back()函数,而只能通过top()函数来访问队首元
素(也可以称为堆顶元素),也就是优先级最高的元素。
程序代码:
#include
#include
using namespace std;
int main(int argc,char** argv) {
priority_queue q;
q.push(3);
q.push(4);
q.push(1);
printf("%d\n",q.top());
return 0;
}
运行结果:
如上所示,队首元素都是优先级最大的,队首元素是4。
(1)push()
push(x)将令x入队,时间复杂度为O(logN),其中N为当前优先队列中的元素个数。实例见“ priority
queue容器内元素的访问”。
(2)top()
top()可以获得队首元素(即堆顶元素),时间复杂度为O(1),实例见" priority_queue容内元素的访
问”。
在使用top()函数前,必须用empty()判断优先队列是否为空。
(3)pop()
pop()可令首元素(即堆顶元素)出队,时间复杂度为O(logN)。
在使用pop()函数前,必须用empty()判断优先队列是否为空。
程序代码:
#include
#include
using namespace std;
int main() {
priority_queue q;
q.push(3);
q.push(4);
q.push(1);
printf("%d\n",q.top());
q.pop();
printf("%d\n",q.top());
return 0;
}
(4)empty()
empty()检测优先队列是否为空,空则返回true,非空则返回false,时间复杂度O(1)。
程序代码:
#include
#include
using namespace std;
int main(){
priority_queue q;
printf("%d\n",q.empty()); //先开始没有元素,为空(true);输出 1
q.push(3);
printf("%d\n",q.empty()); //压入元素,为非看(false);输出 0
return 0;
}
size()返回优先队列内元素的个数,时间复杂度O(1)。
程序代码:
#include
#include
using namespace std;
int main(){
priority_queue q;
for(int i=0;i<=3;i++) {
q.push(i);
}
printf("%d\n",(int)q.size()); //输出队列元素个数
return 0;
}
如何定义优先队列内元素的优先级是运用好优先队列的关键
(1)基本数据类型的优先级设置
此处指的基本数据类型就是int型、 double型、char型等可以直接使用的数据类型,优先队列对它
们的优先级设置一般是数字大的优先级越高,因此队首元素就是优先队列内元素最大的那个(如果
char型,则是字典序最大的)。对基本数据类型来说,下面两种优先队列的定义是等价的(以int型为
例,注意最后两个>之间有一个空格):
priority_queue q;
priority_queue, less > q;
priority_queue, greater > q;
在后二种定义的方式中,多出了两个参数,vector<>和less<>(greater<>)。
第二个参数vector<>是用来承载底层数据结构堆(heap)的容器;
第三个参数less<>或者greater<>是对第一个参数的比较类,less
greater
程序代码:
#include
#include
using namespace std;
int main(){
priority_queue, greater > q;
q.push(3);
q.push(1);
q.push(4);
printf("%d\n",q.top());
return 0;
}
按照正常来说,队头元素应该是最大的元素4,但greater
事实上,基本数据类型也可以使用结构体的优先级设置方法。
(2)结构体的优先级设置
建立结构体,并重载小于号 “<” :
struct fruit {
string name;
int price;
//重载小于号
friend bool operator < (fruit f1, fruit f2) {
return f1.price
定义优先队列:
priority_queue q;
重载是对已有的运算符进行重新定义,在fruit结构体中添加一个函数,其中“friend”是友元;后面的
“bool operator < (fruit f1,fruit f2)”对fruit类型的操作符“<”进制了重载;函数的内部为“return
f1.price 列,其内部以价格高的水果为优先级高。同理想要以价格低的水果为优先级高,那么只需要把 return中的小于号改为大于号即可。 程序代码: 注意: 重载大于号会编译错误,因为从数学上来说只需要重载小于号,即判断f1>f2等价于判断f2 f1==f2则等价于判断!(f1 此处对小于号的重载与排序函数sort中的cmp函数有些相似,它们的参数都是两个变量,函数内部 都是 return了true或者 false。事实上,这两者的作用确实是类似的,只不过效果看上去似乎是“相 反”的。在排序中,如果是“ return f1.price>f2. price”,那么则是按价格从高到低排序,但是在优先 队列中却是把价格低的放到队首。原因在于,优先队列本身默认的规则就是优先级高的放在队首, 因此把小于号重载为大于号的功能时只是把这个规则反向了一下。优先队列的这个函数与sort中的 cmp函数的效果是相反的。 当然也可以将重载的函数写在结构体外面: 定义优先队列: 程序代码: 同样,即便是基本数据类型或者其他STL容器,如(set), 也可以通过同样的方式来定义优先级 最后指出,如果结构体内数据庞大,像出现字符串或者数组,建议使用引用来提高效率。此时比较 类的参数需要加上“const ” 和 “&”,如下所示: 转载:https://blog.csdn.net/qq_42410605/article/details/100537452?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163063047716780366530718%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163063047716780366530718&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-2-100537452.pc_search_result_cache&utm_term=priority_queue&spm=1018.2226.3001.4187#include
struct cmp {
bool operater () (fruit f1,fruit f2) {
return f1.price > f2.price;
}
};
priority_queue
#include
friend bool operator < (const fruit &f1, const fruit &f2) {
return f1.price < f2.price;
}
bool operator () (const fruit &f1, const fruit &f2) {
return f1.price < f2.price;
}