c++的priority_queue各种使用方法

本文详细介绍了C++中的优先队列priority_queue的基础知识,包括其API接口和常数时间复杂度的操作。文章还探讨了如何自定义排序规则,包括使用函数对象、重载运算符、函数指针以及Lambda表达式,并提供了相关示例代码。通过这些方法,读者可以灵活地根据需求调整优先队列的元素排序。
摘要由CSDN通过智能技术生成

一、基础知识

1. priority基本知识

priority_queue 是容器适配器,它提供常数时间的(默认)最大元素查找,对数代价的插入与释出。

可用用户提供的Compare更改顺序,例如,用 std::greater<T> 将导致最小元素作为top()出现。

priority_queue工作类似管理某些随机访问容器中的堆,优势是不可能突然把堆非法化。

priority_queue 容器适配器定义了一个元素有序排列的队列。默认队列头部的元素优先级最高。因为它是一个队列,所以只能访问第一个元素,这也意味着优先级最高的元素总是第一个被处理。但是如何定义“优先级”完全取决于我们自己。如果一个优先级队列记录的是医院里等待接受急救的病人,那么病人病情的严重性就是优先级。如果队列元素是银行的借贷业务,那么借记可能会优先于信贷。

priority_queue 模板有 3 个参数,其中两个有默认的参数;第一个参数是存储对象的类型,第二个参数是存储元素的底层容器,第三个参数是函数对象,它定义了一个用来决定元素顺序的断言。因此模板类型是:


template <typename T, typename Container=std::vector<T>, typename Compare=std::less<T>> class priority_queue

priority_queue 实例默认有一个 vector 容器。函数对象类型 less 是一个默认的排序断言,定义在头文件 function 中,决定了容器中最大的元素会排在队列前面。fonction 中定义了 greater,用来作为模板的最后一个参数对元素排序,最小元素会排在队列前面。当然,如果指定模板的最巵一个参数,就必须提供另外的两个模板类型参数。
在这里插入图片描述

2. priority_queueAPI 接口

优先级队列可以使用任何容器来保存元素,只要容器有成员函数 front()、push_back()、pop_back()、size()、empty()。

priority_queue 进行操作有一些限制:

  1. push(const T& obj):将obj的副本放到容器的适当位置,这通常会包含一个排序操作。
  2. push(T&& obj):将obj放到容器的适当位置,这通常会包含一个排序操作。
  3. emplace(T constructor a rgs...):通过调用传入参数的构造函数,在序列的适当位置构造一个T对象。为了维持优先顺序,通常需要一个排序操作。
  4. top():返回优先级队列中第一个元素的引用。
  5. pop():移除第一个元素。
  6. size():返回队列中元素的个数。
  7. empty():如果队列为空的话,返回true。
  8. swap(priority_queue<T>& other):和参数的元素进行交换,所包含对象的类型必须相同。

二、预备知识

重载函数调用操作符的类,其对象称为函数对象
函数对象使用重载的()时,行为类似函数调用,也叫仿函数
函数对象(仿函数)是一个类,不是一个函数。

三、自定义排序规则

1. 使用函数对象

一般如果使用指针的话,就需要使用函数对象了。

使用函数对象需要注意的是,优先队列在声明的时候采取:

template<
    class T,
    class Container = std::vector<T>,
    class Compare = std::less<typename Container::value_type>
> class priority_queue;

这样的声明方式,

T:参数类型
Container:容器类型。默认是用vector容器实现,参数类型必须是T
Compare:排序规则。默认是小顶堆弹出std::less

  1. 第一个参数为优先队列存储的类型
  2. 第二个参数为实现优先队列的容器类型
  3. 第三个参数为排序的仿函数名称
struct persion{
    int age;
    persion(int a){age = a;}

    bool operator<(const persion& a) const {
        return this->age < a.age;
    }
};

struct cmp{
    bool operator()(persion *a, persion *b) const{
        return a->age < b-> age;
    }
};

int main() {
    cout << "cds:" << endl;
    priority_queue<persion* ,vector<persion*>, cmp> container;
    persion* a = new persion(3);
    container.emplace(a);
    container.emplace(new persion(5));
    container.emplace(new persion(1));
    container.emplace(new persion(4));
    container.emplace(new persion(2));

    while (!container.empty()) {
        cout << container.top()->age << " ";
        container.pop();
    }
    cout << endl;
    return -1;
}
  • 输出
5 4 3 2 1 

2. 自定义类

对于自定义的类,比如persion类,想要进入优先队列进行自动排序,仅需要重载类的<运算符即刻。

struct persion{
    int age;
    persion(int a){age = a;}

    bool operator<(const persion& a) const {
        return this->age > a.age;
    }
};

int main() {

    cout << "重载<运算符:" << endl;
    priority_queue<persion> p;
    p.emplace(persion(4));
    p.emplace(persion(1));
    p.emplace(persion(3));
    p.emplace(persion(2));
    while (!p.empty()) {
        cout << p.top().age << " ";
        p.pop();
    }
    cout << endl;
}
  • 输出:
重载<运算符:
1 2 3 4 

3. 函数指针

bool cmpFun(const Node &a, const Node &b) {
    return a.size == b.size ? a.price > b.price : a.size < b.size;
}
priority_queue<persion, vector<persion>, decltype(cmpFun)*> priorityQueue(cmpFun);

举例:

struct persion{
    int age;
    persion(int a){age = a;}

//    bool operator<(const persion& a) const {
//        return this->age > a.age;
//    }
};

bool cmp_f(const persion& a,const persion& b)  {
    return  a.age < b.age;
}
int main(){
    cout << "函数指针:"  << endl;
    priority_queue<persion ,vector<persion>, decltype(cmp_f)*> dd(cmp_f);
    dd.emplace(persion(4));
    dd.emplace(persion(2));
    dd.emplace(persion(3));
    dd.emplace(persion(1));
    while (!dd.empty()){
        cout << dd.top().age << " ";
        dd.pop();
    }
    cout << endl;
}
  • 输出:
函数指针:
4 3 2 1 

4. 使用lamada表达式

    // 用 lambda 比较元素。
    auto cmp = [](int left, int right) { return (left ^ 1) < (right ^ 1); };
    std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);

附录:源代码

  • 输出:
使用函数对象:
1 2 3 4 5 
重载<运算符:
1 2 3 4 
函数指针:
1 2 3 4 
lamda表达式:
1 2 3 4 
  • 源代码
#include <iostream>
#include <vector>
#include <iostream>
#include <algorithm>
#include <queue>

using namespace std;

struct persion{
    int age;
    persion(int a){age = a;}

    bool operator<(const persion& a) const {
        return this->age > a.age;
    }
};

bool cmp_f(const persion& a,const persion& b)  {
    return  a.age > b.age;
}

struct cmp{
    bool operator()(persion *a, persion *b) const{
        return a->age > b-> age;
    }
};


void funcation_obj();

void opreator_less();

void funcaton_pointer();

void lamada_();

int main() {
    // 1. 函数对象
    funcation_obj();
    // 2. 重载操作服
    opreator_less();
    // 3. 函数指针
    funcaton_pointer();
    // 4. lamada表达式
    lamada_();
    return -1;
}

void lamada_() {
    auto lam = [](persion a, persion b){
        return a.age > b.age;
    };
    cout << "lamda表达式:" << endl;
    priority_queue<persion ,vector<persion>, decltype(lam)> lam_contaner(lam);
    lam_contaner.emplace(persion(1));
    lam_contaner.emplace(persion(4));
    lam_contaner.emplace(persion(3));
    lam_contaner.emplace(persion(2));
    while (!lam_contaner.empty()){
        cout << lam_contaner.top().age << " ";
        lam_contaner.pop();
    }
    cout << endl;
}

void funcaton_pointer() {
    cout << "函数指针:" << endl;
    priority_queue<persion ,vector<persion>, decltype(cmp_f)*> dd(cmp_f);
    dd.emplace(persion(4));
    dd.emplace(persion(2));
    dd.emplace(persion(3));
    dd.emplace(persion(1));
    while (!dd.empty()){
        cout << dd.top().age << " ";
        dd.pop();
    }
    cout << endl;
}

void opreator_less() {
    cout << "重载<运算符:" << endl;
    priority_queue<persion> p;
    p.emplace(persion(4));
    p.emplace(persion(1));
    p.emplace(persion(3));
    p.emplace(persion(2));
    while (!p.empty()) {
        cout << p.top().age << " ";
        p.pop();
    }
    cout << endl;
}

void funcation_obj() {
    cout << "使用函数对象:" << endl;
    priority_queue<persion* ,vector<persion*>, cmp> container;
    persion* a = new persion(3);
    container.emplace(a);
    container.emplace(new persion(5));
    container.emplace(new persion(1));
    container.emplace(new persion(4));
    container.emplace(new persion(2));

    while (!container.empty()) {
        cout << container.top()->age << " ";
        container.pop();
    }
    cout << endl;
}



参考链接:
cppreference: priority_queue

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

早睡的叶子

你的鼓励就是我的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值