相信能看到此文的读者们,一定知道priority_queue的作用,实现大顶堆,小顶堆,但对于自定义数据类型时这个第三个模板参数怎么弄就很迷惑了,而且这种用法和sort的回调函数有一定区别,本文将就这一点进行分析,希望能帮助一些小伙伴的理解,需要对模板及、函数指针、函数对象(仿函数)有一定理解。
·
·
template, class _Pr = less > class priority_queue
这是priority_queue的底层代码,可以看见只要指定第一个参数的类型,后面两个模板参数都会有默认形式,如priority_queue
,则第二个模板参数默认取vector 类型,第三个默认取less 类型(底层是一个结构体)。这都是比较简单的,也不是我想要说的。我想说的是不默认的时候该怎么弄着几个参数,特别是第三个。
·
3 priority_queue的使用方法介绍1.第一种:只定义一个参数,默认形式下,这里是一个关于字符串的大顶堆(按字符串的第一个字符排,最大的在第一位)
priority_queuepq;//也可以是 int,char等
2.第二种:改变第三个模板参数,实现小顶堆需要注意的是也是很多人容易搞不清楚的地方,为什么这里不是sort(v.begin(),v.end(),less
priority_queue,less > pq;
·
3. 第三种:当第一个模板参数是自定义数据时,就需要自定义一个比较方式,可以是一个函数对象,可以是一个函数(一般采用lamda表达式,因为它需要使用当前函数的传入参数,但又不能在函数体内定义函数,故采用这样的方式)。
1)采用函数对象作为第三个模板参数。指定第三个模板参数是cmp类型
struct Node{//也可以是class
int x,y;
Node(int a=0, int b=0):
x(a), y(b) {}
};
struct cmp{//也可以是class
bool operator()(Node a, Node b){
if(a.x == b.x) return a.y>b.y;
return a.x>b.x;
}
};
int main(){
priority_queue, cmp>p;
for(int i=0; i<10; ++i)
p.push(Node(rand(), rand()));
while(!p.empty()){
cout<
·
·
2)这里以leetcode剑指offerII 061的题解代码为例,实现一个第三个参数为函数指针的priority_queue,可以看见它可以按自己想要的方式指定比较函数cmp。而这里采用lamda表达式,因为它需要用到kSmallestPairs的参数,而不写在函数体外。当然这不是重点,重点是decltype(cmp)和 pq(cmp)的使用方式。个人理解是声明cmp函数(实际是以指针)为一个指针类,从而作为模板参数,并在命名的时候使用pq(cmp)。
同时说明cmp在>下实现小顶堆,<实现大顶堆,理解就是后面来的数据在符号右边,如>,它小就返回true,让后面近来的数和前面的数换位置,实现小顶堆。
vector> kSmallestPairs(vector& nums1, vector& nums2, int k){
auto cmp=[&](const pair& lhs, const pair& rhs){
return nums1[lhs.first] + nums2[lhs.second] > nums1[rhs.first] + nums2[rhs.second];
//当后面进来下标pair对rhs下:nums1[rhs.first] + nums2[rhs.second]小时,将这个rhs和lhs置换,实现小顶堆
};
priority_queue, vector>, decltype(cmp)> pq(cmp);
}
4. 总结
如果读者还是不理解可以结合下面几篇高访问文章理解一下,或者留言评论区,当然作者也是初出茅庐,学习这个东西遇到了一些困难,在这里做了一个总结希望帮助到别,有不对之处请大佬指出。
https://blog.csdn.net/weixin_36888577/article/details/79937886
https://blog.csdn.net/xiaoquantouer/article/details/52015928?



