STL 之 优先队列(priority_queue)

1、什么是优先队列

能够完成下列两种操作的数据结构,我们便称之为优先队列。

①插入一个数值    ②取出最大(或者最小)的数值(获取数值,并且删除)。

从严格意义上来说优先队列,并不是队列,因为它并不遵循队列的FIFO(先进先出的原则)。

2、实现优先队列

我们可以使用一种叫做“堆(heap)”的数据结构来实现优先队列。堆有一个重要的性质就是儿子的值一定不小于父亲。除此之外,树的节点是从上到下、从左到右的顺序紧凑排列的。堆就是如下图的二叉树, 不知道是什么是二叉树的同学请移步:传送门

我们向堆插入数值时,首先我们先在堆的尾部插入该值,然后再根据大小关系不断的提升它的位置

删除堆的最小值时,首先把堆的最后一个节点复制到根节点上,然后删除最后一个节点。之后我们根据大小关系不断和交换位置,使其满足堆的定义。

堆的这两种操作所用的时间,和树的深度成正比。我们不难发现堆的时间复杂度为O(log n).

现在我们就可以来实现堆了,为了简单一些我们使用数组来实现:

int heap[MAXN], size_heap = 0;
//插入数值
void push(int x){
    int i = size_heap++;
    while(i > 0){
        //父节点的编号
        int p = (i-1)/2;
        //如果大小关系满足,则退出循环
        if(heap[p] <= x) break;
        //将父节点放下,把自己向上提
        heap[i] = heap[p];
        i = p;
    }
    heap[i] = x;
}
//获取最小值,并删除最小值
int top(){
    //最小值
    int ret = heap[0];
    //最后一个节点
    int x = heap[--size_heap];
    int i = 0;
    while(2*i+1 < size_heap){
        int a = 2*i+1, b = 2*i+2;
        //比较两个儿子的值
        if(b < size_heap && heap[b] < heap[a]) a = b;
        //满足大小关系
        if(heap[a] >= x) break;
        //将数值小的那个儿子提上来
        heap[i] = heap[a];
        i = a;
    }
    heap[i] = x;

    return ret;
}

通过实现堆,我们就大致的对优先队列的原理有了一定的了解。

3、STL之priority_queue

然而很多时候我们并不需要自己实现堆。C++为我们提供了模板类priority_queue。STL的priority_queue包含在头文件queue中, 由于priority_queue使用堆实现,所以我们可以知道priority_queue的时间复杂度应该也为 O(log n)。不过和上述堆实现的优先队列有些许不同。因为priority_queue取出数值时是最大值。我们来看看priority_queue的用法。

<1>priority_queue的基本操作

priority_queue我们常用的有四个成员函数分别

bool empty() const; 返回值为true,则该优先队列为空,反之亦然
size_type size() const; 返回优先队列中元素的数量,size_type是unsigned integral type
void pop(); 删除队列顶部的元素,也就是根节点
void push (const value_type& val); 将元素加入,优先队列中
const_reference top() const; 返回队列顶部的元素,const_reference为队列顶部的类型

<2>改变priority_queue中的排列顺序

在很多时候,我们需要的不一定是最大值,也有可能是最小值。这是就需要我们来改变priority_queue中的顺序。方法有两种:

①如果加入优先队列的是基本类型,那么我们就可以这样,我们以int为例:

//注意greater<int> >这之间有一个空格
priority_queue<int, vector<int>, greater<int> >Q;

②对于自定义数据类型的话,我们不论是要改变排序方式,还是不改变都要这样 --  重载 小于( < ) 运算符:

因为,如果你不重载比较运算符的话,编译器无法比较自定义数据类型的大小关系。然而又因为在priority_queue的内部,只需用到 小于号(<),所以我们只需要重载小于号即可。当然对于自定义数据类型来说,也是必须重载,否则将无法使用priority_queue。重载小于号,我们可以有两种方式,一种用成员函数,一种使用友元函数(这里就不多说了,不会的同学,自己在好好复习复习C++)。

注意:如果使用成员函数重载小于号的话,那么要将重载函数变为常成员函数,否则将无法通过编译。

初步的了解了优先队列之后,我们就可以来两道题巩固,巩固。Expedition
FenceRepair。这两道都是非常有意思的题目,思路比较奇特。



版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-03 21:01:18

STL 之 优先队列(priority_queue)的相关文章

【STL】优先队列priority_queue详解+OpenJudge-4980拯救行动

一.关于优先队列 队列(queue)这种东西广大OIer应该都不陌生,或者说,队列都不会你还学个卵啊(╯‵□′)╯︵┻━┻咳咳,通俗讲,队列是一种只允许从前端(队头)删除元素.从后端(队尾)插入元素的数据结构.而优先队列(priority queue)是一种赋予每个队列中元素以一个优先级的队列.在执行删除操作时,优先队列会删除具有最高优先级的元素.如此奇妙的优先队列有什么用呢,举个例子,给定一个长为n的序列和m组询问,对于每组询问,我们要找出删去序列中最小的数,再向序列加入一个数.朴素的想法是对

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

从我以前的博文能看出来,我是一个队列爱好者,很多并不是一定需要用队列实现的算法我也会采用队列实现,主要是由于队列和人的直觉思维的一致性导致的. 今天讲一讲优先队列(priority_queue),实际上,它的本质就是一个heap,我从STL中扒出了它的实现代码,大家可以参考一下. 首先函数在头文件<queue>中,归属于命名空间std,使用的时候需要注意. 队列有两种常用的声明方式: std::priority_queue<T> pq; std::priority_queue<

c++中STL之heap, priority_queue使用

一.heap heap并不属于STL容器组件,它分为 max heap 和min heap,在缺省情况下,max-heap是优先队列(priority queue)的底层实现机制.而这个实现机制中的max-heap实际上是以一个vector表现的完全二叉树(complete binary tree).STL在<algorithm.h>中实现了对存储在vector/deque 中的元素进行堆操作的函数,包括make_heap, pop_heap, push_heap, sort_heap,对不愿

892A. Greed#贪婪(优先队列priority_queue)

题目出处:http://codeforces.com/problemset/problem/892/A 题目大意:有一些可乐(不一定装满),问能不能把所有可乐装进两个可乐瓶中 #include<iostream> #include<queue> #include<vector> using namespace std; int main(){ priority_queue< long long,vector<long long >,less<lo

优先队列 priority_queue 55 nyist

greater<float> 从小到大lesser<float> 总大到小 #include<queue>#include<iostream>using namespace std;int main(){ int n,m,t,x,y; long long s; priority_queue <int,vector<int>,greater<int> > my; cin>>n; while (n--) { s=0

[C/C++标准库]_[优先队列priority_queue的使用]

std::priority_queue 场景: 1. 对于一个任务队列,任务的优先级由任务的priority属性指明,这时候就需要优先级越高的先执行.而queue并没有排序功能,这时priority_queue是比较好的选择. 2 对于异步的task也是一样,在不断添加新的task时,当然希望优先级越高的先执行. 解析: 1. 如果需要把优先级最高的先pop,那么comp比较时需要返回false. 代码: //1.Elements are popped from the "back"

优先队列priority_queue的简单应用

优先队列 引入 优先队列是一种特殊以及强大的队列. 那么优先队列是什么呢? 说白了,就是一种功能强大的队列. 它的功能强大在哪里呢? 四个字:自动排序. 优先队列的头文件&&声明 头文件: #include<queue> using namespace std; 其次,一个优先队列声明的基本格式是: priority_queue<结构类型> 队列名; priority_queue<int> i; priority_queue<double>

【STL】c++ priority_queue的使用方法

最开始在项目文档看到priority_queue这个模板时,还以为是自己定义的呢,后来查了一下,原来这是STL中存在的一种优先队列. 1.最简单的使用方法 std::priority_queue<int> q;默认从大到小 #include <iostream> #include <queue> #include <vector> int main() { std::priority_queue<int> q; for(int i=0;i<

STL中优先队列的使用

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除.在优先队列中,元素被赋予优先级.当访问元素时,具有最高优先级的元素最先删除.优先队列具有最高级先出的行为特征.我们来说一下C++的STL queue库中优先队列的使用方法.STL默认使用<操作符来确定对象之间的优先级关系,所以如果要使用自定义对象,需要重载<操作符.优先队列有两种,一种是最大优先队列:一种是最小优先队列:每次取自队列的第一个元素分别是优先级最大和优先级最小的元素. 使用头文件queue. 优先队列的操作: q