现在的位置: 首页 > 综合 > 正文

STL priority_queue

2013年08月16日 ⁄ 综合 ⁄ 共 4520字 ⁄ 字号 评论关闭
struct cmp1
{  
    bool operator ()(int &a,int &b)
	{  
        return a>b;//最小值优先   
    }  
};  
struct cmp2
{  
    bool operator ()(int &a,int &b)
	{  
        return a<b;//最大值优先   
    }  
};  
struct node1
{  
    int u;  
    bool operator < (const node1 &a) const 
	{  
       return u>a.u;//最小值优先   
    }  
};  
struct node2
{  
	int u;  
	bool operator < (const node2 &a) const 
	{  
        return u<a.u;//最大值优先   
	}  
}; 

priority_queue<int>q1;//采用默认优先级构造队列     
priority_queue<int,vector<int>,cmp1>q2;//最小值优先   
priority_queue<int,vector<int>,cmp2>q3;//最大值优先   
priority_queue<int,vector<int>,greater<int> >q4;//注意“>>”会被认为错误,   
                                                //这是右移运算符,所以这里用空格号隔开,最小值优先 
priority_queue<int,vector<int>,less<int> >q5;//最大值优先    
priority_queue<node1>q6;  //自定义优先级
priority_queue<node2>q7;

STL之priority_queue【转】
 

STL之优先队列

原本以为priority_queue很简单,才知道原来懂的只是最简单的形式。

头文件:#include<queue>

优先队列,也就是原来我们学过的堆,按照自己定义的优先级出队时。默认情况下底层是以Vector实现的heap

既然是队列,也就只有入队、出队、判空、大小的操作,并不具备查找功能。

函数列表:
empty() 如果优先队列为空,则返回真 
pop()
 删除第一个元素 
push()
 加入一个元素 
size()
 返回优先队列中拥有的元素的个数 
top()
 返回优先队列中有最高优先级的元素

用途就不用多说了吧,例如Huffman编码、分支限界、A*启发式都需要用到优先队列存放信息。

来看最常用的几个功能,了解一下其中的知识点:

一:最基本的功能

#include<iostream>

#include<queue>

using namespace std;

int main()

{

    priority_queue<int> Q;

    Q.push(2);

    Q.push(5);

    Q.push(3);

    while(!Q.empty())

    {

           cout<<Q.top()<<endl;

           Q.pop();

    }  

    system("pause");

    return 0;

}

  

优先队列最基本的功能就是出队时不是按照先进先出的规则,而是按照队列中优先级顺序出队。

知识点:1、一般存放实型类型,可比较大小

2、默认情况下底层以Vector实现

3、默认情况下是大顶堆,也就是大者优先级高,后面可以自定义优先级比较规则

二:次基本的功能

#include<iostream>

#include<queue>

using namespace std;

int main()

{

    int a[5]={3,4,5,2,1};

    priority_queue<int> Q(a,a+5);

    while(!Q.empty())

    {

           cout<<Q.top()<<endl;

           Q.pop();

    }  

    system("pause");

    return 0;

}

可以将一个存放实型类型的数据结构转化为优先队列,这里跟优先队列的构造函数相关。

上面那个默认构造一个空的优先队列,什么都使用默认的。

而这里使用的是

Priority_queue(InputIterator first,InputIterator last)

我理解的就是给出了一个容器的开口和结尾,然后把这个容器内容拷贝到底层实现(默认vector)中去构造出优先队列。这里也使用了一个默认的比较函数,也是默认大顶堆

三 应该掌握的功能:

 

#include<iostream>

#include<queue>

using namespace std;

 

typedef pair<long,int> Node;

 

priority_queue< Node,vector< Node >,greater< Node > > Q;

 

 

这个里面定义了一个制定存放元素(Node),底层实现以vector实现(第二个参数),优先级为小顶堆(第三个参数)

前两个参数没什么说的,很好理解,其中第三个参数,默认有三写法:

小顶堆:greater<TYPE>

大顶堆:less<TYPE>

如果想自定义优先级而TYPE不是基本类型,而是复杂类型,例如结构体、类对象,则必须重载其中的operator(),见下面的例子。

 

 

 

例子:

#include<iostream>

#include<queue>

using namespace std;

 

//模拟存放节点信息

typedef struct

{

int a;

int b;      

}Node;

//自定义优先级类型

struct cmp

{

       bool operator()(const Node &t1,const Node &t2)

       {

            return t1.b<t2.b;//相当于less,大顶堆    

       }

};

int main()

{

    //初始化

   int n;

   cin>>n;

   Node *arr=new Node[n];

   for(int i=0;i<n;i++)

   {

          cin>>arr[i].a>>arr[i].b;       

   }

   //定义优先队列 ,自定义优先级,Qsort里面自定义相似

   priority_queue<Node,vector<Node>,cmp> Q(arr,arr+n);

   while(!Q.empty())

   {

         Node n=Q.top();

         cout<<n.a<<" "<<n.b<<endl;

         Q.pop();             

   }

    system("pause");

    return 0;

}

View
Code

这里可以看到priority_queue的接口使用情况,priority_queue是容器适配器(也有书称之为容器配接器),默认使用适配容器为vector,当然也可以使用其他的适配容器,其默认的比较函数模板是less,即大顶堆。

priority_queue函数模板的成员函数如下:

View
Code

复制代码
Member functions
(constructor) Construct priority queue (public member function) 
empty Test whether container is empty (public member function) 
size     Return size (public member function) 
top      Access top element (public member function) 
push   Insert element (public member function) 
pop     Remove top element (public member function) 
复制代码

 

下面我们先来看一个简单的应用。

View
Code

上面的比较函数为默认less,元素大的优先级高,构造的是大顶堆,所以输出不难理解。

但是如果我们想让上述元素从小到大排列优先级怎么办?我们需要传入比较函数,使用functional.h中的函数对象作为比较函数。如下格式

View
Code

 

如果我们想自定义自己的比较函数怎么办呢?比如说很多时候我们比较的并不是内嵌式数据类型,我们可能比较的是我们自定义的结构体关系,需要独立的比较函数。

则我们需要考察调用机制。在为优先级队列建立默认堆的时候我们需要使用一个比较函数模板,代码如下:

View
Code

复制代码
template<class _Ty>
    struct less
        : public binary_function<_Ty, _Ty, bool>
    {    // functor for operator<
    bool operator()(const _Ty& _Left, const _Ty& _Right) const
        {    // apply operator< to operands
        return (_Left < _Right);
        }
    };
复制代码

问题就处在这行代码。我们使用了"<"操作符,内嵌式的类型编译器都定义好了这种操作符,而我们自定义的结构体或者类没有重载这个操作符,这样找不到函数调用,从而导致错误,

如何解决这个问题呢,我们只有自己动手丰衣足食,重载这个默认的操作符如下。

View
Code

复制代码
struct MyType
{
    friend bool operator< (MyType T1,MyType T2)
    {
        return T1.priority < T2.priority;
    }
    int priority;
    ElemType value;
};
复制代码

但是有的童鞋可能要问,我不想用“<”操作符,我要实现的是">"操作符,定义大于关系,于是这位童鞋定义了这个

View
Code

复制代码
struct MyType
{
    friend bool operator> (MyType T1,MyType T2)
    {
        return T1.priority > T2.priority;
    }
    int priority;
    ElemType value;
};
复制代码

问题来了,编译器还是找不到<操作符调用,为什么呢,呵呵?因为我们优先级队列定义的完整类型是这个

View
Code

priority_queue<MyType, vector<MyType>, less<MyType> > Q;  priority_queue<MyType > Q的完整类型

这里使用的比较函数模板是less,里面只用到“<”操作符。当然你也可以如下声明

View
Code

复制代码
struct MyType
{
    friend bool operator< (MyType T1,MyType T2)
    {
        return T1.priority > T2.priority;
    }
    int priority;
    ElemType value;
};
复制代码

但是不直观,STL为大于比较函数定义了greater模板,和less函数类模板一样,只不过使用的是">"操作符,因此,我们可以如下声明和使用priority_queue

View
Code

复制代码
struct MyType
{
    friend bool operator> (MyType T1,MyType T2)
    {
        return T1.priority > T2.priority;
    }
    int priority;
    ElemType value;
};

priority_queue<MyType, vector<MyType>, greater<MyType> >Q;
复制代码

抱歉!评论已关闭.