优先级队列priority_queue的介绍与使用

目录

杂谈

成员函数

构造函数

top

push

pop

empty

swap 

size

emplace

测试代码(使用场景)


杂谈

优先级队列priority_queue是位于头文件<queue>中的一个类,它和queue一样,也是一个队列,只不过该队列是按照优先级进行过排列的,priority_queue底层的结构本质就是一个堆,默认是大堆,这一点和下图的模板参数Compare有关。

优先级队列priority_queue也是一个容器适配器,如下图中第二个模板参数就表示priority_queue应该适配什么容器完成priority_queue的功能,可以看到下图中STL标准库默认选择vector<T>作为优先级队列的默认适配容器,为什么不是deque呢?因为优先级队列底层就是一个堆,在插入或删除数据时需要AdjustUp或者AdjustDown调整数据,这需要大量使用operator[],deque虽然也支持operator[],但在<<stack与queue的模拟实现、对deque的了解性学习>>一文中也说过相比于vector的operator[]底层直接挪动指针,deque的operator[]计算比较复杂,大量使用时会降低性能,因此vector<T>更适合做优先级队列的默认适配容器。第三个模板参数表示一种可调用对象的类型,比如可以是函数的类型,仿函数的类型,函数指针的类型。他是干嘛的呢?是用于给优先级队列确定元素优先级的一套比较规则。规则可以规定:值较大的元素优先级高。规则也可以规定:值较小的元素优先级高。

优先级队列不支持迭代器,如果支持迭代器会导致优先级没法被保证了。

成员函数

构造函数

1.默认构造,都有缺省值,如果显示传参,则需要给形参comp传一个可调用对象,如函数对象(仿函数),函数,函数指针,Compare就表示这些对象的类型;需要给第二个参数cntr传一个容器对象,但注意有一个前提,那就是priority_queue必须适配该容器,如何判断是否适配该容器呢?如下图所示。

2.迭代器区间构造,迭代器类型可以是任意容器的迭代器,如可以通过list的迭代器区间构造优先级队列。

top

取优先级队列中优先级最高的元素,也就是队列中的极大或者极小值,如何判断是极大还是极小呢?看优先级队列的底层实现是建立大堆还是小堆,top函数用于取堆顶的元素,因此如果是大堆,则堆顶的元素是最大值,所以top函数就是用于取优先级队列中的极大值,反之则是极小值。

push

用于将一个元素放进优先级队列中。

pop

用于删除优先级队列中优先级最高,也就是堆顶的元素。

empty

用于判断优先级队列中是否存在有效数据,即是否为空。

swap 

用于交换两个优先级队列对象管理的有效数据。noexcept表示该函数不会抛异常。

size

用于返回优先级队列中有效数据的个数。

emplace

功能和push一样,效率比push高,但会导致代码可读性下降。

测试代码(使用场景)

可以看到值较大的元素优先级较高,即底层的堆顶是极大值,所以STL中的优先级队列底层默认是建大堆的。 

那如何让较小的元素优先级较高,也就是让优先级队列的底层是建立小堆呢?如下图两个红框所示,添加头文件<functional>,然后将greater<int>类传给优先级队列的第三个模板参数。注意如果想传greater<int>给第三个模板参数,则必须先传值给第二个模板参数,如下图传了vector<int>给二个模板参数,否则编译器会认为greater<int>是传给第二个模板参数的值,这是一个缺省值的小知识点。说一下如何记忆greater和less分别对应的是大堆还是小堆:因为向下调整法是比向上调整法更优的,因此STL中的priority_queue在建堆时(不管是大堆还是小堆),都是通过向下调整法完成的。然后要知道的是只要函数对象的成员函数operator()返回true,就表示准许进行向下调整,比如说greater表示>,只要我们控制在x>y时返回true,那么就表示准许让x向下进行调整,那么较大的值就都在堆的较下方,所以也就是建小堆了;同理,less表示<,只要我们控制在x<y时返回true,那么就表示准许让x向下进行调整,那么较小的值就都在堆的较下方,所以也就是建大堆了。

如下图问题也可以通过优先级队列巧妙的解决。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值