C++优先级队列priority_queue自定义比较函数

1.自定义数据类型时

https://blog.youkuaiyun.com/HermitSun/article/details/107101944

 参照378. 有序矩阵中第 K 小的元素

复制代码

class Point
{
    int val, x, y;
    Point(int val, int x, int y) : val(val), x(x), y(y) {}
    bool operator>(const Point &p) const { return val > p.val; }
};

复制代码

自定义 定义一个小顶堆,这里的greater运算符函数,参数需要是const,并且需要时const函数,不然会报错:

this‘ argument has type ‘const xxx‘, but method is not marked const

 初始化时:

priority_queue<Point, vector<Point>, greater<Point>> q;

  q.emplace(1, 1, 1);

greater函数的文档:

也就是说在堆排序时,调用greater,greater的参数是const的,并且是const成员函数,在内部比较时会用到上面重写的operator>函数,而const成员函数不能调用非const成员函数,所以会报错,所以需要将其声明为const函数,另外如果operator>的参数列表不声明为const,但operator中为const会导致形参无法赋值。

2.三种方法

https://www.cnblogs.com/Harley-Quinn/p/6104306.html

2.1函数指针

bool greaterInt(const int& lhs, const int& rhs)
{
    return lhs > rhs;
}
priority_queue<int, vector<int>, bool(*)(const int&, const int&)> q(greaterInt);

但这样写其实是写的复杂了,C风格的,不常用。

 2.2函数对象

仿函数类

复制代码

template <typename T>
struct Greater
{
    bool operator()(const T& lhs, const T& rhs) const
    {
        return lhs > rhs;
    }
};
priority_queue<int, vector<int>, Greater<int>> q;

复制代码

采用显式写法:

priority_queue<int, vector<int>, Greater<int>> q(Greater<int>());

即显式地调用Greater类的默认构造函数,但这样会报错,所以不要这样。

2.3 lamda表达式

    auto comp = [](const int& lhs, const int& rhs) { return lhs > rhs; };
    priority_queue<int, vector<int>, decltype(comp)> q(comp);

官方文档中给出的具体的例子,https://en.cppreference.com/w/cpp/container/priority_queue/priority_queue:

复制代码

#include <iostream>
#include <queue>
#include <vector>
#include <utility>
 
using my_pair_t = std::pair<size_t,bool>;
 
using my_container_t = std::vector<my_pair_t>;
 
int main()
{
    auto my_comp =
        [](const my_pair_t& e1, const my_pair_t& e2) 
        { return e1.first > e2.first; };
    std::priority_queue<my_pair_t,
                        my_container_t,
                        decltype(my_comp)> queue(my_comp);
    queue.push(std::make_pair(5, true));
    ....
}

复制代码

但是结合第一节中的讨论,如果存储的类型是指针类型,那么参数就不能是const的,有两个具体的举例:

23. 合并K个升序链表
        auto cmp=[](const ListNode* & a,const ListNode* & b){return a->val>b->val;};//不能用const,是错的!OMG
        priority_queue<ListNode*,vector<ListNode*>,decltype(cmp)> pq(cmp);

注意,定义的cmp参数类型是指针类型,并且是const的,提交会报错:

 本人手动尝试了基本类型的指针:

复制代码

    auto comp = [](const int*& lhs, const int*& rhs) { return *lhs > *rhs; };
    priority_queue<int*, vector<int*>, decltype(comp)> q(comp);
    int* a=new int(5);
    int *b=new int(6);
    q.push(a);
    q.push(b);

复制代码

会报错:

error: cannot bind non-const lvalue reference of type 'const int*&' to an rvalue of type 'const int*'

搜索相关的结果都是  临时变量不能用作非const引用。所以这个错误的原因未知。

总的修改之后:

        auto cmp=[](ListNode*& a, ListNode*& b){return a->val>b->val;};
        priority_queue<ListNode*,vector<ListNode*>,decltype(cmp)> pq(cmp);

 ok.

复制代码

    auto comp = [](int* & lhs, int* & rhs) { return *lhs > *rhs; };
    priority_queue<int*, vector<int*>, decltype(comp)> q(comp);
    int* a=new int(5);
    int *b=new int(6);
    q.push(a);
    q.push(b);

复制代码

 ok.

所以如果T是指针类型,那么函数形参中不加const。

3.sort中的cmp函数与优先队列priority_queue的重载函数重载小于号)的区别

https://blog.youkuaiyun.com/weixin_44980441/article/details/107365028

复制代码

struct fruit
{
    string name;
    int price ;
    friend bool operator < (fruit a,fruit b)
    {
        return a.price>b.price;//低价优先!!!!。
    }
};

复制代码

bool cmp(fruit a,fruit b){
    return a.price>b.price;//高价优先
}

非常易错,到现在也分不清。。。

C++ 中,`priority_queue` 是一种优先队列容器,它会根据元素的优先级对元素进行排序。当需要自定义元素的优先级时,就需要使用自定义比较函数。以下是几种常见的自定义比较函数的使用方法和示例: ### 方法一:使用比较结构体 通过定义一个结构体,并在其中重载 `()` 运算符来实现自定义比较。 ```cpp #include<queue> #include<vector> #include<iostream> using namespace std; struct node { int x, y; node(int x, int y):x(x),y(y){} }; // 比较结构体 struct cmp { bool operator()(node a, node b) { if(a.x == b.x) return a.y >= b.y; else return a.x > b.x; } }; int main() { priority_queue<node,vector<node>,cmp> pq; for(int i = 1; i <= 5; i++) for(int j = 1; j <= 5; j++) pq.push(node(i,j)); while(!pq.empty()) { cout<<pq.top().x<<" "<<pq.top().y<<endl; pq.pop(); } return 0; } ``` 在这个示例中,定义了 `node` 结构体表示元素,`cmp` 结构体作为比较函数。`priority_queue` 的模板参数中指定了元素类型 `node`、底层容器 `vector<node>` 和比较函数 `cmp` [^5]。 ### 方法二:重载小于运算符 将小于运算符重载为友元函数,来改变元素的比较规则。 ```cpp #include <iostream> #include <queue> struct Node{ int val; // 重载小于运算符,必须以友元函数的形式 friend bool operator<(const Node &a, const Node &b){ return a.val > b.val; } }; int main() { priority_queue<Node, vector<Node>> q; q.push({3}); q.push({1}); q.push({2}); while (!q.empty()) { std::cout << q.top().val << std::endl; q.pop(); } return 0; } ``` 此示例中,重载了 `Node` 结构体的小于运算符,使得 `priority_queue` 按照 `val` 从小到大的顺序排列元素 [^4]。 ### 方法三:使用自定义结构体在 `main` 函数示例 ```cpp #include <iostream> #include <algorithm> #include <queue> #include <cstdio> using namespace std; struct Node{ int x; int y; Node(int a=0, int b=0) { x = a; y = b; } }; struct cmp{ bool operator () (Node a, Node b) { if(a.x == b.x) return a.y > b.y; else return a.x < b.x ; } }; int main() { priority_queue <Node, vector<Node>, cmp > q; for(int i = 0; i < 10; ++i ) { q.push(Node(i,10-i)); } while( !q.empty()) { cout << q.top().x << ' ' << q.top().y << endl; q.pop(); } return 0; } ``` 这个示例中,同样使用了自定义的 `Node` 结构体和 `cmp` 比较结构体,`priority_queue` 根据 `cmp` 定义的规则对 `Node` 元素进行排序 [^1]。 ### 方法四:在结构体内部重载小于运算符示例 ```cpp #include<iostream> #include<queue> using namespace std; struct node { friend bool operator< (node n1, node n2) { return n1.priority < n2.priority; } int priority; int value; }; int main() { priority_queue<node> q; const int len = 5; node b[len]; b[0].priority = 6; b[0].value = 1; b[1].priority = 9; b[1].value = 5; b[2].priority = 2; b[2].value = 3; b[3].priority = 8; b[3].value = 2; b[4].priority = 1; b[4].value = 4; for (int i = 0; i < len; i++) q.push(b[i]); cout << "优先级" << '\t' << "值" << endl; for (int i = 0; i < len; i++) { cout << q.top().priority << '\t' << q.top().value << endl; q.pop(); } return 0; } ``` 此示例在 `node` 结构体内部重载了小于运算符,使得 `priority_queue` 按照 `priority` 从大到小的顺序排列元素 [^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值