C++中STL的优先队列priority_queue详解

 更新时间:2023年08月23日 10:03:14   作者:吃代码的喵酱-i  
这篇文章主要介绍了C++中STL的优先队列priority_queue详解,今天讲一讲优先队列(priority_queue),实际上,它的本质就是一个heap,我从STL中扒出了它的实现代码,需要的朋友可以参考下

浅谈C++ STL中的优先队列(priority_queue) 

首先函数在头文件中,归属于命名空间std,使用的时候需要注意。

队列有两种常用的声明方式:

std::priority_queue<T> pq;
std::priority_queue<T, std::vector<T>, cmp> pq;

第一种实现方式较为常用,接下来我给出STL中的对应声明,再加以解释。

template<class _Ty,
    class _Container = vector<_Ty>,
    class _Pr = less<typename _Container::value_type> >
    class priority_queue

大家可以看到,默认模板有三个参数,第一个是优先队列处理的类,第二个参数比较有特点,是容纳优先队列的容器。

实际上,优先队列是由这个容器+C语言中关于heap的相关操作实现的。

这个容器默认是vector,也可以是dequeue,因为后者功能更强大,而性能相对于vector较差,考虑到包装在优先队列后,后者功能并不能很好发挥,所以一般选择vector来做这个容器。

第三个参数比较重要,支持一个比较结构,默认是less,默认情况下,会选择第一个参数决定的类的<运算符来做这个比较函数。

接下来开始坑爹了,虽然用的是less结构,然而,队列的出队顺序却是greater的先出!

就是说,这里这个参数其实很傲娇,表示的意思是如果!cmp,则先出列,不管这样实现的目的是啥,大家只能接受这个实现。

实际上,这里的第三个参数可以更换成greater,像下面这样:

std::priority_queue<T, std::vector<T>, greater<T>> pq;

一般大家如果是自定义类就干脆重载<号时注意下方向了,没人在这里麻烦,这个选择基本上是在使用int类还想小值先出列时。

从上面的剖析我们也就知道了,想要让自定义类能够使用优先队列,我们要重载小于号。

class Student
{
    int id;
    char name[20];
    bool gender;
    bool operator < (Student &a) const
    {
        return id > a.id;
    }
};

就拿这个例子说,我们想让id小的先出列,怎么办,就要很违和的给这个小于符号重载成实际上是大于的定义。

如果我们不使用自定义类,又要用非默认方法去排序怎么办?

就比如说在Dijkstra中,我们当然不会用点的序号去排列,无论是正序还是反序,我们想用点到起点的距离这个值来进行排序,我们怎样做呢?

优先队列默认使用的是小于结构,而上文的做法是为我们的自定义类去定义新的小于结构来符合优先队列,我们当然也可以自定义比较结构。

自定义方法以及使用如下,我直接用Dijkstra代码来说明:

int cost[MAX_V][MAX_V];
int d[MAX_V], V, s;
//自定义优先队列less比较函数
struct cmp
{
    bool operator()(int &a, int &b) const
    {
        //因为优先出列判定为!cmp,所以反向定义实现最小值优先
        return d[a] > d[b];
    }
};
void Dijkstra()
{
    std::priority_queue<int, std::vector<int>, cmp> pq;
    pq.push(s);
    d[s] = 0;
    while (!pq.empty())
    {
        int tmp = pq.top();pq.pop();
        for (int i = 0;i < V;++i)
        {
            if (d[i] > d[tmp] + cost[tmp][i])
            {
                d[i] = d[tmp] + cost[tmp][i];
                pq.push(i);
            }
        }
    }
}

优先队列的日常使用,了解上面那些就已经足够。下面给出优先队列的所有成员函数的STL实现方法,希望你看完没有一脸卧槽的感觉。c就是你声明时候的那个vector或者其他容器。

    void push(value_type&& _Val)
        {    // insert element at beginning
        c.push_back(_STD move(_Val));
        push_heap(c.begin(), c.end(), comp);
        }
    template<class... _Valty>
        void emplace(_Valty&&... _Val)
        {    // insert element at beginning
        c.emplace_back(_STD forward<_Valty>(_Val)...);
        push_heap(c.begin(), c.end(), comp);
        }
    bool empty() const
        {    // test if queue is empty
        return (c.empty());
        }
    size_type size() const
        {    // return length of queue
        return (c.size());
        }
    const_reference top() const
        {    // return highest-priority element
        return (c.front());
        }
    void push(const value_type& _Val)
        {    // insert value in priority order
        c.push_back(_Val);
        push_heap(c.begin(), c.end(), comp);
        }
    void pop()
        {    // erase highest-priority element
        pop_heap(c.begin(), c.end(), comp);
        c.pop_back();
        }

到此这篇关于C++中STL的优先队列priority_queue详解的文章就介绍到这了,更多相关STL的优先队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++设置超时时间的简单实现方法

    C++设置超时时间的简单实现方法

    这篇文章主要介绍了C++设置超时时间的简单实现方法,涉及系统函数setsockopt对套接口的操作,具有一定的实用价值,需要的朋友可以参考下
    2014-10-10
  • C语言中数组作为函数的参数以及返回值的使用简单入门

    C语言中数组作为函数的参数以及返回值的使用简单入门

    这篇文章主要介绍了C语言中数组作为函数的参数以及返回值的使用简单入门,这里以一维数组作为基本条件进行例子讲解,需要的朋友可以参考下
    2015-12-12
  • C语言冷门知识之你可能没听过的柔性数组

    C语言冷门知识之你可能没听过的柔性数组

    柔性数组(Flexible Array)是引入的一个新特性,它允许你在定义结构体时创建一个空数组,而这个数组的大小可以在程序运行的过程中根据你的需求进行更改特别注意的一点是:这个空数组必须声明为结构体的最后一个成员,并且还要求这样的结构体至少包含一个其他类型的成员
    2021-10-10
  • C++中atof 函数的介绍

    C++中atof 函数的介绍

    这篇文章主要给大家分享的是C++中atof 函数的介绍,在 stdlib.h 中 atof 函数,可用于将 char 字符串转为 float / double 浮点数类型,想具体了解语法的小伙伴可以参考下面文章的内容,希望对大家有所帮助
    2021-11-11
  • Cocos2d-x触摸事件实例

    Cocos2d-x触摸事件实例

    这篇文章主要介绍了Cocos2d-x触摸事件实例,本文代码中包含大量注释来说明Cocos2d-x中的触摸事件使用示例,需要的朋友可以参考下
    2014-09-09
  • C++开发:为什么多线程读写shared_ptr要加锁的详细介绍

    C++开发:为什么多线程读写shared_ptr要加锁的详细介绍

    本篇文章介绍了,在C++中为什么多线程读写shared_ptr要加锁的详细说明。需要的朋友参考下
    2013-04-04
  • C++中的STL中map用法详解(零基础入门)

    C++中的STL中map用法详解(零基础入门)

    map在编程中是经常使用的一个容器,本文来讲解一下STL中的map,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • c++先序二叉树的构建详解

    c++先序二叉树的构建详解

    在本篇文章里小编给大家分享了关于c++先序二叉树的构建的相关知识点,需要的朋友们跟着学习下。
    2019-04-04
  • Qt QString的使用实现

    Qt QString的使用实现

    本文主要介绍了Qt QString的使用实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-05-05
  • 一文带你快速了解C/C++标准库中的ptrdiff_t

    一文带你快速了解C/C++标准库中的ptrdiff_t

    ptrdiff_t是C/C++标准库中定义的一个与机器相关的数据类型,ptrdiff_t类型变量通常用来保存两个指针减法操作的结果,下面这篇文章主要给大家介绍了关于C/C++标准库中ptrdiff_t的相关资料,需要的朋友可以参考下
    2022-11-11

最新评论