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++代码解答示例,文中包括ACM竞赛的八皇后相关知识的练习实例,需要的朋友可以参考下
    2015-08-08
  • 用C语言进行最基本的socket编程

    用C语言进行最基本的socket编程

    这篇文章主要介绍了C语言下socket编程的基本知识讲解,包括最基本的客户端发送及服务器端接受数据的实现,需要的朋友可以参考下
    2015-11-11
  • 讲解C++中的枚举类型以及声明新类型的方法

    讲解C++中的枚举类型以及声明新类型的方法

    这篇文章主要介绍了讲解C++中的枚举类型以及声明新类型的方法,是C预言入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C++中declspec(dllexport)和declspec(dllimport) 的用法介绍

    C++中declspec(dllexport)和declspec(dllimport) 的用法介绍

    这篇文章介绍了C++中declspec(dllexport)和declspec(dllimport) 的用法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • C语言大作业之图书管理系统的实现详程

    C语言大作业之图书管理系统的实现详程

    随着网络技术的高速发展,计算机应用的普及,利用计算机对图书馆的日常工作进行管理势在必行,趁着寒假时间手把手带你用C语言实现一个图书管理系统,大家可以在过程中查缺补漏,提升水平
    2022-01-01
  • C++变量和基本类型详解

    C++变量和基本类型详解

    这篇文章主要介绍了C++变量和基本类型,,一定要注意局部变量与全局变量的作用范围,需要的朋友可以参考下,希望能够给你带来帮助
    2021-10-10
  • C++using声明和using编译指令

    C++using声明和using编译指令

    这篇文章主要介绍了C++using声明和using编译指令,C++当中提供了两种机制来简化对名称空间中名称的使用。using声明使特定的标识符keys,using编译指令使整个名称空间可用。下面我们就来看看这两种机制的相关资料吧,需要的小伙伴可以参考一下
    2021-12-12
  • C语言打印华氏-摄氏温度对照表的方法

    C语言打印华氏-摄氏温度对照表的方法

    这篇文章主要介绍了C语言打印华氏-摄氏温度对照表的方法,涉及C语言字符串与数字操作的相关技巧,非常简单实用,需要的朋友可以参考下
    2015-07-07
  • C/C++的关键字之static你了解吗

    C/C++的关键字之static你了解吗

    这篇文章主要为大家详细介绍了C/C++的关键字之static,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++归并排序代码实现示例代码

    C++归并排序代码实现示例代码

    归并排序将待排序数组分成两个子数组,分别对这两个子数组进行排序,然后将排序好的子数组合并,得到排序后的数组,这篇文章主要介绍了C++归并排序代码实现的相关资料,需要的朋友可以参考下
    2025-08-08

最新评论