STL容器——priority_queue用法笔记

1. priority_queue定义

默认容器为vector,默认比较方式为大顶堆 less<type>

priority_queue<typename> name;

自定义方式: 

Type是要存放的数据类型;Container是实现底层堆的容器,必须是数组实现的容器,如vector、deque;Functional是比较方式/比较函数/优先级

priority_queue<Type,Container,Functional> name;
//pair
priority_queue<pair<int, int> > a;
pair<int, int> b(1, 2);
pair<int, int> c(1, 3);
pair<int, int> d(2, 5);
a.push(d);
a.push(c);
a.push(b);
while (!a.empty()) 
{
   cout << a.top().first << ' ' << a.top().second << '\n';
   a.pop();
}
//输出结果为:
2 5
1 3
1 2

2. priority_queue容器内元素的访问

优先队列没有front()函数和back()函数,只能通过top()函数来访问队首元素

3.priority_queue常用函数

(1)push()

(2)top()

(3)pop()

(4)empty()

(5)size()

(6)emplace()

4.priority_queue内元素优先级的设置

(1)基本数据类型的优先级设置

默认一般数字越大、字典序越大,优先级越高。对基本数据类型来说,以下两种优先队列的定义等价:

priority_queue<int> q;
priority_queue<int,vector<int>,less<int>> q;

//Type是要存放的数据类型

//Container是实现底层堆的容器,必须是数组实现的容器,如vector、deque

//Functional是比较方式/比较函数/优先级

less<int>:数字大的优先级越大,大顶堆
greater<int>:数字小的优先级越大,小顶堆

//小顶堆:
priority_queue<int,vector<int>,greater<int>> q;

//大顶堆:
priority_queue<int,vector<int>,less<int>> q;

//默认大顶堆:
priority_queue<int> q;

(2)结构体的优先级设置

定义一个结构体:

struct fruit{
    string name;
    int price;
};

当数据类型并不是基本数据类型,而是自定义的数据类型时,就不能用greater或less的比较方式了,而是需要自定义比较方式

有两种自定义比较方式的方法,重载运算符和仿函数,使用如下:

1.重载运算符—传入双参数

运算符重载:对已有运算符进行重新定义

(1) 希望按水果价格高的为优先级高,构造大顶堆,重载小于号“<”:
struct fruit{
    string name;
    int price;
    friend bool operator<(fruit f1,fruit f2){
        return f1.price<f2.price;
    }
};

friend:友元
bool operator<(friend f1,friend f2):对fruit类型操作符"<"进行了重载
此时可直接定义fruit类型的优先队列,其内部以价格高的水果为优先级高:

priority_queue<fruit> q;

完整代码如下:

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

struct fruit{
    string name;
    int price;
    friend bool operator<(fruit f1,fruit f2){
        return f1.price>f2.price;
    }
}f1,f2,f3;

int main(){
    priority_queue<fruit> q;
    f1.name="桃子";
    f1.price=3;
    f2.name="梨子";
    f2.price=4;
    f3.name="苹果";
    f3.price=1;
    q.push(f1);
    q.push(f2);
    q.push(f3);
    cout<<q.top().name<<" "<<q.top().price<<endl;
    return 0;
}

//输出结果:
//苹果 1
(2) 希望按水果价格低的为优先级高,构造小顶堆,重载小于号“<”:
struct fruit{
    string name;
    int price;
    friend bool operator<(fruit f1,fruit f2){
        return f1.price>f2.price;
    }
};
(3) 重载大于号会编译错误,从数学上来说只需要重载小于号:

f1>f2 等价于判断 f2<f1
f1==f2 等价于判断 !(f1<f2)&&!(f2<f1)

2.重载运算符—传入单参数

重载运算符语句:

返回类型 operator 重载运算符(参数)const {内容}
​传入单参数对比传入双参数,()内只有一个参数,()后多加一个const

bool operator<(const node& x) const{
    return a<x.a;//大顶堆
}

//完整写法:
struct node{
    int a,b;
    bool operator<(const node& x) const{
        return a<x.a;//或 return this->a<x.a;
    }
};
#include<iostream>
#include<queue>
using namespace std;

struct node{
	int a,b,c;
	bool operator<(const node& x) const{
		return a<x.a;
	}
};
priority_queue<node,vector<node>,less<node> > q;//大根堆 

int main(){
	node x1={1,2,3};
	node x2={1,3,2};
	node x3={2,3,1};
	q.push(x1);
	q.push(x2);
	q.push(x3);
	while(!q.empty()){
		printf("%d %d %d\n",q.top().a,q.top().b,q.top().c);
		q.pop();
	}
	return 0;
}

//输出结果:
2 3 1
1 3 2
1 2 3
3.仿函数

将重载运算符中的friend去掉,小于号改为一对小括号,将重载函数写在结构体外,同时将struct包装起来

struct cmp{
    bool operator()(fruit f1,fruit f2){
        return f1.price>f2.price;
}

此时需要用第二种定义方式来定义优先队列:

priority_queue<fruit,vector<fruit>,cmp> q;

 完整代码如下:

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

struct fruit{
    string name;
    int price;
}f1,f2,f3;

struct cmp{
    bool operator()(fruit f1,fruit f2){
        return f1.price>f2.price;
    }
};

int main(){
    priority_queue<fruit,vector<fruit>,cmp> q;
    f1.name="桃子";
    f1.price=3;
    f2.name="梨子";
    f2.price=4;
    f3.name="苹果";
    f3.price=1;
    q.push(f1);
    q.push(f2);
    q.push(f3);
    cout<<q.top().name<<" "<<q.top().price<<endl;
    return 0;
}

//输出结果:
//苹果 1
4. 重载运算符和仿函数注意事项:

如果结构体内数据较为庞大,如出现字符串或数组,建议使用引用来提高效率,此时比较类的参数需要加上"const"和"&",如下所示:

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

使用结构体内重载运算符,定义优先队列priority_queue时不用写上完整的三个参数,参数写上结构体即可:

priority_queue<fruit> q;

5. priority_queue的常见用途和注意事项

priority_queue可以解决一些贪心问题,也可以对Dijkstra算法进行优化(优先队列的本质是堆)
需要注意的是,使用top()函数前,必须使用empty()判断优先队列是否为空,否则可能因为队空而出现错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值