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