C++ priority_queue的自定义比较方式

19 篇文章 0 订阅
9 篇文章 0 订阅

经常需要用优先队列来进行一些算法的优化,于是今天对优先队列的排序方式做一个小结:

首先,先手写一个小根堆,再分析代码:

#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;
}

最近学习STL,发现STL默认都是使用()比较的,默认比较使用less(即'<'运算符),如sort(a,a+n),默认将数组按照递增的顺序来排序(前面的元素<后面的嘛),但是优先队列的源码比较奇特,虽然按道理使用less比较应该默认是小根堆(即堆顶元素最小),但是priority_queue<>默认是大根堆的,这是因为优先队列队首指向最后,队尾指向最前面的缘故!每次入队元素进去经排序调整后,优先级最大的元素排在最前面,也就是队尾指向的位置,这时候队首指向优先级最小的元素!所以虽然使用less但其实相当于greater,我们重载运算符的时候比较函数里面写>就相当于<排序方式,这点需要花点时间想想,再来说一说优先队列的这个类型,其实有三个参数:priority_queue<class Type,class Container,class Compare>,即类型,容器和比较器,后两个参数可以缺省,这样默认的容器就是vector,比较方法是less,也就是默认大根堆,可以自定义写比较方法,但此时若有比较方法参数,则容器参数不可省略!priority_queue<>的可支持的容器必须是用数组实现的容器,如vector,deque,但不能是list(推荐vector),比较方法可以写结构体重载()运算符,也可以用less,greater这些语言实现了的,但是灵活性不够,建议手写重载结构体,或者——如果不想写比较结构体的话,就将后面的两个参数缺省,直接重载类型的<运算符,如:

#include<queue>
#include<iostream>
using namespace std;

struct node
{
    int x, y;
    node(int x,int y):x(x),y(y){}
};

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> pq;    //只传node,但是node结构体的<运算符已被改变
    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;
}

也可以写在结构体里面,只用一个参数,但是需要常量修饰符修饰和引用修饰参数,并且函数外面也需要const:

#include<queue>
#include<iostream>
using namespace std;

struct node
{
      int x, y;
      node(int x, int y):x(x),y(y){}
      bool operator< (const node &b) const   //写在里面只用一个b,但是要用const和&修饰,并且外面还要const修饰;
      {
           if(x == b.x)  return y >= b.y;
           else return x > b.x;
      }
};

int main()
{
    priority_queue<node> 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;
}

最后说一句,以上三段代码运行结果都是一样的,为:

嗯,大概就是这样,less和greater的比较就不写了,有兴趣可以上网查一查使用方法

priority_queue自定义比较可以通过重载小于操作符或者自定义函数对象来实现。 通过重载小于操作符,可以定义一个结构体或者类,并在其中重载小于操作符来比较元素的优先级。比如,可以定义一个结构体 MyType,重载小于操作符,使得元素按照 val 从大到小排序。 ``` struct MyType { int val; bool operator<(const MyType& other) const { return val > other.val; // 从大到小排序 } }; priority_queue<MyType> pq; ``` 另一种方法是通过定义函数对象来实现自定义比较。可以创建一个结构体或类,并在其中重载()操作符,然后作为模板参数传递给 priority_queue。比如,可以定义一个类 cmp,重载了()操作符,使得小的元素在队尾,优先级越低。 ``` struct cmp { bool operator()(int a,int b){ return a < b; // 小的放左边,即less } }; priority_queue<int,vector<int>,cmp> pq; ``` 还可以使用函数指针来自定义比较。可以定义一个函数,接受两个参数,并返回一个 bool 值,表示第一个元素是否比第二个元素优先。然后将函数指针作为模板参数传递给 priority_queue。例如,可以定义一个函数对象 cmp,重载了()操作符,使得大的元素在队尾,优先级越低。 ``` bool cmp(int a, int b) { return a > b; // 大的放左边,即greater } priority_queue<int, vector<int>, bool (*)(int, int)> pq(cmp); ``` 以上是三种常见的自定义比较方法,可以根据实际需求选择其中一种来实现自定义比较。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [优先队列之自定义比较函数](https://blog.csdn.net/yrk0556/article/details/87994924)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [c++优先队列priority_queue自定义比较函数)](https://blog.csdn.net/qq_21539375/article/details/122128445)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [一文看懂priority_queue自定义比较函数有几种方法](https://blog.csdn.net/weixin_36389889/article/details/129802998)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值