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的优先队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Qt拖放操作和打印操作的实现

    Qt拖放操作和打印操作的实现

    本文主要介绍了Qt拖放操作和打印操作的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • C++容器vector实现通讯录功能

    C++容器vector实现通讯录功能

    这篇文章主要为大家详细介绍了C++容器vector实现通讯录功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • Matlab利用遗传算法GA求解非连续函数问题详解

    Matlab利用遗传算法GA求解非连续函数问题详解

    遗传算法起源于对生物系统所进行的计算机模拟研究。其本质是一种高效、并行、全局搜索的方法,能在搜索过程中自动获取和积累有关搜索空间的知识,并自适应地控制搜索过程以求得最佳解。本文将利用其求解非连续函数问题,需要的可以参考一下
    2022-09-09
  • C语言静态链表和动态链表

    C语言静态链表和动态链表

    静态链表和动态链表是线性表链式存储结构的两种不同的表示方式。静态链表的初始长度一般是固定的,在做插入和删除操作时不需要移动元素,仅需修改指针。动态链表是相对于静态链表而言的,一般地,在描述线性表的链式存储结构时如果没有特别说明即默认描述的是动态链表。
    2016-05-05
  • 手把手教你用C语言实现三子棋

    手把手教你用C语言实现三子棋

    三子棋是黑白棋的一种。三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、井字棋等。这篇文章就教你如何用C语言实现三子棋的功能
    2021-08-08
  • C语言实现万年历效果

    C语言实现万年历效果

    这篇文章主要为大家详细介绍了C语言实现万年历效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-11-11
  • 基于matlab对比度和结构提取的多模态解剖图像融合实现

    基于matlab对比度和结构提取的多模态解剖图像融合实现

    这篇文章主要介绍了多模态医学图像配准与融合的概念、方法及意义,最后简单介绍了小波变换分析方法。感兴趣的小伙伴可以跟随小编一起学习一下
    2021-11-11
  • C++实现俄罗斯方块

    C++实现俄罗斯方块

    这篇文章主要为大家详细介绍了C++实现俄罗斯方块,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • Matlab计算变异函数并绘制经验半方差图详解

    Matlab计算变异函数并绘制经验半方差图详解

    这篇文章主要为大家详细介绍了基于MATLAB求取空间数据的变异函数,并绘制经验半方差图的方法。文中的示例代码讲解详细,感兴趣的可以了解一下
    2023-04-04
  • C语言超详细讲解线性表

    C语言超详细讲解线性表

    线性表,数据结构中最简单的一种存储结构,专门用于存储逻辑关系为"一对一"的数据。线性表是基于数据在实际物理空间中的存储状态,又可细分为顺序表(顺序存储结构)和链表
    2022-07-07

最新评论