STL | priority_queue(优先队列)基本用法

写在前面:

priority_queue ,又称优先队列 ,是一个容器——允许在时间复杂度下插入 数据、在时间复杂度下取得容器内最大(最小)值

其本质就是一个 ,只是比我们自己手写堆 多了一些优化罢了(没有优化也就不会纳入STL中啦)。

使用STL的priority_queue需要包含头文件queue ,即

#include

优先队列:

一. 定义

优先队列priority_queue的定义如下:

template<
    class T,
    class Container = std::vector,
    class Compare = std::less
> class priority_queue;
Parameter Description Default
T The type of object stored in the priority queue.
Container The type of the underlying container used to implement the priority queue. vector
Compare The comparison function used to determine whether one element is smaller than another element.If Compare(x,y) is true, then x is smaller than y.The element returned by Q.top() is the largest element in the priority queue.That is, it has the property that, for every other element x in the priority queue, Compare(Q.top(), x) is false. less
参数 描述 默认值
数据类型 T 优先队列中存放的数据类型
容器 用于实现优先队列(潜在)的容器类型 vector
比较函数(优先级) 用于确定一个元素是否小于另一个元素的比较函数。如果Compare(x, y)是正确的,那么x小于y,优先队列Q.top()返回的就是最大的元素。此时,优先队列队头元素Q.top()与优先队列Q中所有其他元素x进行比较,即Compare(Q.top (), x) 是错误的 less
  • Container:必须是用数组实现的容器,比如 vector, deque,但不能用 list。STL里面默认用的是 vector。

  • Compare:比较方式默认用使用less,operator <(小于号)。

  • 所以如果你把后面俩个参数缺省的话,优先队列就是大顶堆,队头元素最大。


二. 默认的优先队列——大顶堆

priority_queueque;
等价于
priority_queue,less >que;
注意需要添加头文件vector,即#include 
可以在下面的测试程序中,动手尝试一下
#include
#include
#include
#include
#include
#include
using namespace std;

priority_queueque;// 默认的优先队列 
//priority_queue,less >que;
int test[1010];

int main()
{
    // 使用一个简易的随机数(不能超过值RAND_MAX)进行测试 
    srand((int)time(0)); 
    for(int i=0;i<100;i++)test[i]=rand(),que.push(test[i]);
    // 入队列之前 
    cout<<"Before:\n";
    for(int i=0;i<100;i++)cout<
默认的优先队列

三. 更改比较函数——仿函数greater

默认的优先队列是大顶堆,那么,如果我们想要变为小顶堆 ,可以使用STL中的仿函数
greater
(默认的使用的是less)。

对上面的程序中,优先队列的定义进行如下修改,

priority_queue,greater >que;

重新运行程序,得到下面结果(可以看出此时优先队列相当于一个小顶堆 )。

greater

四. 自定义类型——大顶堆

STL中的仿函数less和greater的使用范围仅限于基本类型,当优先队列需要保存我们自定义的数据类型时,我们需要重载小于号(operator <)或者写仿函数,这两种方式定义的优先队列稍有不同。

① 重载小于运算符 <:

// 重载 < 运算符,实现大顶堆
//(堆顶元素:先根据x,选择x最大的元素;若两个元素的x值相同,再根据y,选择两者中y较大的元素) 
bool operator<(My_Type a,My_Type b)
{
    // 定义排序规则 
    if(a.x==b.x) return a.yque; 

② 仿函数:

// 仿函数,实现大顶堆 
struct cmp
{
    // 定义排序规则 
    bool operator() (My_Type a,My_Type b )
    { 
        if(a.x==b.x)return a.y,cmp>que;

③ 完整代码:

#include
#include
#include
#include
#include
#include
using namespace std;
// 自定义一种结构体类型 
typedef struct
{
    int x;
    int y;
}My_Type;
// 仿函数,实现大顶堆 
struct cmp
{
    // 定义排序规则 
    bool operator() (My_Type a,My_Type b )
    { 
        if(a.x==b.x)return a.yvec;
//priority_queue,cmp>que;
priority_queueque; 

int main()
{
    My_Type temp;
    srand((int)time(NULL)); 
    for(int i=0;i<10;i++)
    {
        temp.x=rand();
        temp.y=rand();
        vec.push_back(temp);
        que.push(temp);
    }
    cout<<"Before:\n";
    for(int i=0;i<10;i++)
    {
        cout<
自定义类型——大顶堆

五. 自定义类型——小顶堆

若要实现一个小顶堆,与上面的程序差不多,仅仅需要更改一下排序规则即可:
① 重载小于运算符 <:

// 重载 < 运算符,实现小顶堆 
bool operator<(My_Type a,My_Type b)
{
    // 定义排序规则 
    if(a.x==b.x) return a.y>b.y;
    return a.x>b.x; 
}

② 仿函数:

// 仿函数,实现小顶堆 
struct cmp
{
    // 定义排序规则 
    bool operator() (My_Type a,My_Type b )
    { 
        if(a.x==b.x)return a.y>b.y;
        return a.x>b.x; 
    }
}; 

六. 优先队列的用途:

一开始我们便提到了,优先对了是一个容器——允许在时间复杂度下插入 数据、在时间复杂度下取得容器内最大(最小)值

正是由于优先队列这样的特征(时间复杂度低),使得在一些算法中可以使用优先队列来进行优化:

  • 哈夫曼树 & 哈夫曼编码

  • 最小生成树的Prim算法

  • 单源最短路径Dijkstra算法

(PS:未完待续,遇到了再做补充)


七. 其他一些常见的函数:

函数 功能
empty() 如果优先队列为空,则返回真
top() 返回优先队列中有最高优先级的元素
pop() 删除第一个元素
push() 插入一个元素
size() 返回优先队列中拥有的元素的个数

写在最后:

参考资料:

  • 博客:C++ priority_queue(优先队列)使用
  • 博客:C++STL priority_queue 学习
  • 博客:priority_queue的用法

优先队列,虽然叫队列,但是其本质却是堆(一种特殊的二叉树)。

看待一个人,以貌取人往往是不够的,更多的是看他生活的点滴,从生活的蛛丝马迹中了解一个人。

你可能感兴趣的:(STL | priority_queue(优先队列)基本用法)