当前位置:   article > 正文

STL之priority_queue优先队列_优先队列stl

优先队列stl

主页面目录

5. priority_queue

5.1 介绍

优先队列是在正常队列的基础上加了优先级,保证每次的队首元素都是优先级最大的。

可以实现每次从优先队列中取出的元素都是队列中优先级最大的一个。

它的底层是通过来实现的。

//头文件
#include<queue>
//初始化定义
priority_queue<int> q;
  • 1
  • 2
  • 3
  • 4

5.2 函数方法

代码含义
q.top()访问队首元素 O ( 1 ) O(1) O(1)
q.push()入队 O ( l o g N ) O(logN) O(logN)
q.pop()堆顶(队首)元素出队 O ( l o g N ) O(logN) O(logN)
q.size()队列元素个数 O ( 1 ) O(1) O(1)
q.empty()是否为空 O ( 1 ) O(1) O(1)
注意没有clear()不提供该方法
优先队列只能通过top()访问队首元素(优先级最高的元素)

5.3 设置优先级

5.3.1 基本数据类型的优先级

priority_queue<int> pq; // 默认大根堆, 即每次取出的元素是队列中的最大值
priority_queue<int, vector<int>, greater<int>> q; // 小根堆, 每次取出的元素是队列中的最小值
  • 1
  • 2

参数解释:

  • 第一个参数:就是优先队列中存储的数据类型

  • 第二个参数:

    vector<int> 是用来承载底层数据结构堆的容器,若优先队列中存放的是double型数据,就要填vector< double >
    总之存的是什么类型的数据,就相应的填写对应类型。同时也要改动第三个参数里面的对应类型。

  • 第三个参数:
    less<int> 表示数字大的优先级大,堆顶为最大的数字
    greater<int>表示数字小的优先级大,堆顶为最小的数字
    int代表的是数据类型,也要填优先队列中存储的数据类型


下面介绍基础数据类型优先级设置的写法:

  1. 基础写法(非常常用):
priority_queue<int> q1; // 默认大根堆, 即每次取出的元素是队列中的最大值
priority_queue<int, vector<int>, less<int> > q2; // 大根堆, 每次取出的元素是队列中的最大值,同第一行

priority_queue<int, vector<int>, greater<int> > q3; // 小根堆, 每次取出的元素是队列中的最小值
  • 1
  • 2
  • 3
  • 4
  1. 自定义排序(不常见,主要是写着麻烦):

下面的代码比较长,基础类型优先级写着太麻烦,用第一种即可。

struct cmp1 {
	bool operator()(int x, int y) {
		return x > y;
	}
};
struct cmp2 {
	bool operator()(const int x, const int y) {
		return x < y;
	}
};
priority_queue<int, vector<int>, cmp1> q1; // 小根堆
priority_queue<int, vector<int>, cmp2> q2; // 大根堆
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

5.3.2 高级数据类型(结构体)优先级

即优先队列中存储结构体类型,必须要设置优先级,即结构体的比较运算(因为优先队列的堆中要比较大小,才能将对应最大或者最小元素移到堆顶)。

优先级设置可以定义在结构体内进行小于号重载,也可以定义在结构体外

//要排序的结构体(存储在优先队列里面的)
struct Point {
	int x, y;
};
  • 1
  • 2
  • 3
  • 4
  • 版本一:自定义全局比较规则
//定义的比较结构体
//注意:cmp是个结构体 
struct cmp {//自定义堆的排序规则 
	bool operator()(const Point& a,const Point& b) {
		return a.x < b.x;
	}
};

//初始化定义, 
priority_queue<Point, vector<Point>, cmp> q; // x大的在堆顶
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 版本二:直接在结构体里面写

因为是在结构体内部自定义的规则,一旦需要比较结构体,自动调用结构体内部重载运算符规则。

结构体内部有两种方式:

方式一

struct node {
	int x, y;
	friend bool operator < (Point a, Point b) {//为两个结构体参数,结构体调用一定要写上friend
		return a.x < b.x;//按x从小到大排,x大的在堆顶
	}
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

方式二 :(推荐此种)

struct node {
    int x, y;
    bool operator < (const Point &a) const {//直接传入一个参数,不必要写friend
        return x < a.x;//按x升序排列,x大的在堆顶
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

优先队列的定义

priority_queue<Point> q;
  • 1

注意: 优先队列自定义排序规则和sort()函数定义cmp函数很相似,但是最后返回的情况是相反的。即相同的符号,最后定义的排列顺序是完全相反的。
所以只需要记住sort的排序规则和优先队列的排序规则是相反的就可以了。

当理解了堆的原理就会发现,堆调整时比较顺序是孩子和父亲节点进行比较,如果是 > ,那么孩子节点要大于父亲节点,堆顶自然是最小值。

5.4 存储特殊类型的优先级

5.4.1 存储pair类型

  • 排序规则:
    默认先对pairfirst进行降序排序,然后再对second降序排序
    first先排序,大的排在前面,如果first元素相同,再对second元素排序,保持大的在前面。

pair请参考下文

#include<bits/stdc++.h>
using namespace std;
int main() {
    priority_queue<pair<int, int> >q;
	q.push({7, 8});
	q.push({7, 9});
	q.push(make_pair(8, 7));
    while(!q.empty()) {
        cout << q.top().first << " " << q.top().second << "\n";
        q.pop();
    }
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

结果:
8 7
7 9
7 8

如要获取所有内容的PDF文件,请在公众号【行码棋】回复【STL】获取,非常抱歉了。
Update:2023-12-11更新PDF文件

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/355194
推荐阅读
相关标签
  

闽ICP备14008679号