例说数据结构&STL(七)——priority_queue

1 白话优先队列(priority_queue)
  前面我们已经相继介绍了双向队列和FIFO特性的队列,这里我们还要接触另一个包含“队列”称呼的数据结构——优先队列。其实这三个数据结构名称看似很像,实则天差万别,通过下面的介绍你就会有很深的体会了。
  那么何为优先队列呢,在优先队列中,元素被赋予优先级,当访问元素时,具有最高级优先级的元素先被访问。即优先队列具有最高级先出的行为特征。所以说队列queue可以看成是优先队列的一个特殊情况,其中的数据优先级别是按数据的插入时间先后排序的,这种插入时间的先后就可以看做是一种优先级。在默认的优先队列中,优先级最高的先出队。默认的int类型的优先队列中先出队的为队列中较大的数。
  介绍到此,你是不是发现它有些像构建堆呢?也就是大顶堆表示优先级最高的先出队,而小顶堆表示优先级别最低的先出队。
2 STL中priority_queue实战
 2.1 包含heap的头文件
  priority_queue和queue一样定义在同一个头文件中的,另外使用一直强调的std命名空间一定要加上,实现如下:

#include<queue>

using namespace std;

 2.2 声明优先队列对象
  优先队列模板类的构造实际上有三个类型需要给出,默认构造如下:

priority_queue<int> que1;       // 普通构造,默认是大顶堆

priority_queue<int> que2(10,3);// 带参构造初始化10个数据3

  此外我们还可以手工构造,这样就可以定义为大顶堆还是小顶堆了,如下:

priority_queue<int, vector<int>, less<int>>    //大顶堆:表示其他都比堆顶小
priority_queue<int, vector<int>, greater<int>> //小顶堆:表示其他都比堆顶大

  所以默认情况下是less构建的大顶堆,表示其中的数越来越小。要记住,如果是要手工确认优先级规则,那么内部使用的容器一定也要手动加上,不可以是priority_queue<int, greater<int>>这样定义。
  另外,上面的less和greater是定义在functional.h头文件中,如果使用这样的系统自带功能函数一定要加上对应的头文件。当然我们也可以自定义优先规则,这个后面再详细说明。
 2.3 基本操作
  基本操作和队列大致相同,除了队列既可以访问队首也可以访问队尾,而优先队列只能访问队首,所以访问接口不同,其他几乎一样。此外优先队列也是适配器类型容器,所以没有对应的迭代器功能定义。基本操作如下:

que1.empty( );  // 判断队列是否为空

que1.pop( );    // 删除队顶元素

que1.push( );   // 加入一个元素

que1.size( );   // 返回优先队列中拥有的元素个数

que1.top( );    // 返回队顶元素,接口和stack名一样。而queue中是front()和back()

 2.4 自定义优先级规则
  优先级的规则定义常用是下面两种方法,主要都是构建一个结构体,一种方法是在结构体中重载运算符(),而另一种是构建一个友元的函数重载运算符<。

// 自定义优先级规则
struct cmp
{
    bool operator()(int a, int b) //重载运算符(),参数是int后面只能声明int类型优先队列
    {
        return a < b; //最大值优先,如果a>b就是最小值优先
    }
};

priority_queue<int,vector<int>,cmp> que; //只能是构建int类型有限队列

  首先结构体中重载运算符类型决定了你构建优先队列模板类类型,如果是重载运算符()中参数类型是string,则构建优先队列只能是string类型。此外比较的大小符号决定构建最大堆还是最小堆。
  另外一种方法如下:

//定义结构,使用成员函数运算符重载<自定义优先级1 
struct node{  
    int x;  
    bool operator < (const node &a) const {  
        return x>a.x;  // 最小值优先,<则为最大值优先  
    }  
}; 

//定义结构,使用友元函数运算符重载<自定义优先级2 
struct node{  
    int x;  
    friend bool operator < (const node &a, const node &b) const {  
        return a.x>b.x;   // 最小值优先,<则为最大值优先  
    }  
}; 

priority_queue<node> que; // 构建node类型的优先队列对象
node num[]={14,10,56,7,83,22,36,91,3,47}; // 创建多个结构体的对象,并且初始化数据x
for(int& i : num)
{
    que.push(i); // 依次读进node,根据参数x优先排列
}

  成员函数和友元函数两种表达方式都行,使用该方法则优先队列的类型需要就是该结构体,并且优先队列的前后顺序由结构体中比较符和对应参数决定。此处需要注意,重载>号会编译出错,因为标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。而且自定义优先级与重载操作运算符类型并无直接联系,我们按规则行事即可。

3 小结
  上面介绍了优先队列数据结构特点以及STL中包含的接口。由于优先队列是基于堆完成敬意,所以其存取的时间复杂度为O(logn),n为队列中元素的个数。
  以上是个人学习记录,由于能力和时间有限,如果有错误望读者纠正,谢谢!
  转载请注明出处:http://blog.csdn.net/FX677588/article/details/76359337


  参考文献:
  http://blog.csdn.net/u011240016/article/details/59266961
  http://blog.csdn.net/ac_gibson/article/details/44200411
  http://www.cnblogs.com/heqinghui/archive/2013/07/30/3225407.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值