您的位置:首页 > 理论基础 > 数据结构算法

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

2017-07-29 23:41 274 查看
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: