C++ 优先队列的基本使用方法


[cpp]
  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<cstdio>  
  2. #include<queue>  
  3. using namespace std;  
  4.   
  5. priority_queue<int> da;  //大根堆  
  6. priority_queue<int,vector<int>,greater<int> > xiao;  //小根堆,最后的两个“>”之间要有空格,vector不用单另开头文件。至于greater是什么意思,我并不知道……  

 
 

转自http://blog.csdn.net/senyelicone/article/details/51850284   ,在此对博主表示感谢~

C++中优先队列(priority queue<>)使用头文件queue,需要声明using namespace std;

常用来代替堆,每次直接加入新数即可,自动维护大小顺序,使用很方便。

以大根堆为例,q.top( )是队中最大的数。常用操作还有:q.push_back(x),q.pop( ) …

上面的程序是基本的建立队列,可以建立大根堆或小根堆,不必强制记忆,每次调试一下就可以了。

(以上是优先队列中常用内容,下面是转载的很神奇的用法。(感觉用不到))

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include<iostream>  
  2. #include<functional>  
  3. #include<queue>  
  4. using namespace std;  
  5. struct node  
  6. {  
  7.     friend bool operator< (node n1, node n2)  
  8.     {  
  9.         return n1.priority < n2.priority;  //"<"为从大到小排列,">"为从小到大排列  
  10.     }  
  11.     int priority;  
  12.     int value;  
  13. };  
  14. int main()  
  15. {  
  16.     const int len = 5;  //也可以写在函数内  
  17.     int i;  
  18.     int a[len] = {3,5,9,6,2};  
  19.     //示例1  
  20.     priority_queue<int> qi;  //普通的优先级队列,按从大到小排序  
  21.     for(i = 0; i < len; i++)  
  22.         qi.push(a[i]);  
  23.     for(i = 0; i < len; i++)  
  24.     {  
  25.         cout<<qi.top()<<" ";  
  26.         qi.pop();  
  27.     }  
  28.     cout<<endl;  
  29.     //示例2  
  30.     priority_queue<int, vector<int>, greater<int> > qi2;  //从小到大的优先级队列,可将greater改为less,即为从大到小  
  31.     for(i = 0; i < len; i++)  
  32.         qi2.push(a[i]);  
  33.     for(i = 0; i < len; i++)  
  34.     {  
  35.         cout<<qi2.top()<<" ";  
  36.         qi2.pop();  
  37.     }  
  38.     cout<<endl;  
  39.     //示例3  
  40.     priority_queue<node> qn;  //必须要重载运算符  
  41.     node b[len];  
  42.     b[0].priority = 6; b[0].value = 1;  
  43.     b[1].priority = 9; b[1].value = 5;  
  44.     b[2].priority = 2; b[2].value = 3;  
  45.     b[3].priority = 8; b[3].value = 2;  
  46.     b[4].priority = 1; b[4].value = 4;  
  47.    
  48.     for(i = 0; i < len; i++)  
  49.         qn.push(b[i]);  
  50.     cout<<"优先级"<<'\t'<<"值"<<endl;  
  51.     for(i = 0; i < len; i++)  
  52.     {  
  53.         cout<<qn.top().priority<<'\t'<<qn.top().value<<endl;  
  54.         qn.pop();  
  55.     }  
  56.     return 0;  
  57. }  



对于队列里元素为一个结构体类型,按照某一个属性排序,就需要对比较函数进行重载

小结一下:

1、若是定义值类型对象,如: 


[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int main()   
  2. {        
  3.     priority_queue<node> qn;  
  4.     node n1;   
  5.     n1.a = 9;   
  6.     node n2;   
  7.     n2.a = 2;   
  8.     node n3;   
  9.     n3.a = 50;    
  10.     qn.push(n1);  
  11.     qn.push(n2);  
  12.     qn.push(n3);  
  13.      int  size = qn.size();  
  14.      for ( int  i = 0; i < size; i++)   
  15.     {   
  16.         cout << qn.top().a << endl;  
  17.         qn.pop();   
  18.     }   
  19.          return  0;  
  20. }   



则定义优先级的时候,直接在类中写个friend 的操作符重载函数即可: 


[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class  node   
  2. {   
  3. public :   
  4.      int  a;  
  5.     node(){}   
  6.     node( int  x):a(x){}   
  7. friend   bool  operator<( const  node ne1, const  node ne2)//参数也可以为引用,值传递   
  8.     {   
  9.          if (ne1.a > ne2.a)   
  10.         {   
  11.              return   true ;   
  12.         }   
  13.          else   
  14.         {   
  15.              return   false ;   
  16.         }   
  17.     }   
  18. };   



其中在c++primer第三版 中文版中关于操作符重载有如下描述:

"程序员只能为类类型或枚举类型的操作数定义重载操作符我们可以这样来实现把重 
载操作符声明为类的成员或者声明为名字空间成员同时至少有一个类或枚举类型的参数 
按值传递或按引用传递"

因此不可用指针类型的参数

2、如果想定义一个指针类型的优先队列,那就不可这么简单的定义了,你需要自定义一个自己的比较函数,在priority_queue的模板函数中,我们可以利用这样一个template<class _Ty, class _Container = vector<_Ty>, class _Pr = less<typename _Container::value_type> >模板,在我们的程序代码中,则需要自己定义一个类来定义第三个模板参数,如:

class  nodePointerComparer  
{  
public :  
    nodePointerComparer(){}  
     bool  operator ()( const  node* ne1,  const  node* ne2)  const   
    {  
         return  ne1->lessthan(ne2);  
    }  
};  

当然在这之前我们的类Node要重新书写 

class  node  
{  
public :  
     int  a;  
    node(){}  
    node( int  x):a(x){} 

     bool  lessthan( const  node* pnode)  const   
    {  
         return  a < pnode->a;  
    }  
};  
这样在main函数中就可以定义指针类型的优先队列了:

int  main()  
{  
    priority_queue <node*, vector <node*>, nodePointerComparer> qn;  
    node *n1 =  new  node(90);  
    node *n2 =  new  node(2);  
    node *n3 =  new  node(50); 

    qn.push(n1);  
    qn.push(n2); /span>


    qn.push(n3); 

     int  size = qn.size();  
     for ( int  i = 0; i < size; i++)  
    {  
        cout << qn.top()->a << endl;  
        qn.pop();  
    }  
     return  0; 

}  
疑问之处:如果你使用第一种值传递的操作符重载,来实现第二种的指针类型优先队列,是不会达到想要的结果的,个人理解是因为在指针类型的优先队列中找“<”运算符的时候,重载的不是我们写的值传递friend bool operator<(const node ne1,const node ne2)//

也就是没有找到指针类型的"<"重载,所有不会达到优先队列的效果。

猜你喜欢

转载自blog.csdn.net/sumword_/article/details/54847254