zoukankan      html  css  js  c++  java
  • (转)【C++ STL】细数C++ STL 的那些事 -- priority_queue(优先队列)

    装载自http://blog.csdn.net/tianshuai1111/article/details/7652553

    一,概述

               priority_queue是拥有权值观念的queue,它允许加入新元素,移除旧元素。调用 STL里面的 make_heap(), pop_heap(), push_heap() 算法实现,也算是堆的另外一种形式。但它是一个queue所以只允许在底端加入元素,在顶端移除元素。

               排序:按照权值大小顺序排序,而不是按照push 进去的顺序排序。权值高者排在前面,权值低者排在后面。

               允许以任何大小顺序插入到优先队列,但取出时是按照权值大小取。          

    二,heap(堆)简介

            1)采用vector存储,是一颗完全二叉树(complete binary tree)的形式。

                   heap分为 max_heap 和 min_heap,前者最大权值在根,后者最小权值在根。

            2)建立堆过程

                  vector中元素先调整为堆的形式。

                  插入元素时,将元素放到vector 的最后面end(),然后上溯调整堆。

            3)heap算法      // #include <algorithm>

                   make_heap(first,last)       //初建堆

                   push_heap(first,last)        //插入元素,并调整为堆

                   pop_heap(first,last)         //弹出元素,并调整为堆

                   sort_heap(first,last)         //堆排序

             4)示例

     1 #include <cstdlib>
     2 #include <iostream>
     3 #include <vector>
     4 #include <algorithm>
     5 
     6 using namespace std;
     7 
     8 int main(int argc, char** argv) {
     9 
    10     
    11     int ia[9]={0,1,2,3,4,5,6,7,8};
    12     vector<int> ivec(ia,ia+9);
    13     
    14     make_heap(ivec.begin(),ivec.end()); //#include <algorithm>
    15     for(int i=0;i<ivec.size();++i)
    16         cout<<ivec[i]<<" ";
    17     cout<<endl;
    18     
    19     ivec.push_back(7);
    20     push_heap(ivec.begin(),ivec.end());
    21     for(int i=0;i<ivec.size();++i)
    22         cout<<ivec[i]<<" ";
    23     cout<<endl;
    24     
    25     pop_heap(ivec.begin(),ivec.end());  
    26     cout<<ivec.back()<<endl; //返回刚刚弹出的堆顶
    27     ivec.pop_back();         //将最后一个元素弹出数组
    28     
    29     for(int i=0;i<ivec.size();++i)
    30         cout<<ivec[i]<<" ";
    31     cout<<endl;
    32     
    33     sort_heap(ivec.begin(),ivec.end());
    34     for(int i=0;i<ivec.size();++i)
    35         cout<<ivec[i]<<" ";
    36     cout<<endl;
    37     
    38     return 0;
    39 }
    View Code

    三,priority_queue 实例

     1 #include <queue>
     2 #include <algorithm>
     3 #include <iostream>
     4 using namespace std;
     5 
     6 
     7 int main(int argc, char** argv) {
     8 
     9     int ia[9]={1,2,4,3,6,5,9,8,7};
    10     priority_queue<int>  ipq(ia,ia+9);
    11     cout<<"size:"<<ipq.size()<<endl;
    12     
    13     for(int i=0;i<ipq.size();++i)
    14         cout<<ipq.top()<<" ";
    15     cout<<endl;
    16     
    17     while(!ipq.empty())
    18     {
    19         cout<<ipq.top()<<" ";
    20         ipq.pop();
    21     }
    22     
    23     return 0;
    24 }
    View Code

     2)自己实现priority_queue  

                 STL里面的 priority_queue 写法与此相似,只是增加了模板及相关的迭代器

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <vector>
     4  
     5 using namespace std;
     6 class priority_queue
     7 {
     8     private:
     9         vector<int> data;        
    10     public:
    11         void push( int t ){
    12             data.push_back(t);
    13             push_heap( data.begin(), data.end());//将动态数组vector中元素 建立成堆
    14         }        
    15         void pop(){
    16             pop_heap( data.begin(), data.end() ); //弹出堆顶元素,并调整堆
    17             data.pop_back();
    18         }        
    19         int top() { return data.front(); }
    20         int size() { return data.size(); }
    21         bool empty() { return data.empty(); }
    22 };
    23  
    24  
    25 int main()
    26 {
    27     priority_queue test;
    28     test.push( 3 );
    29     test.push( 5 );
    30     test.push( 2 );
    31     test.push( 4 );
    32      
    33     while( !test.empty() ){
    34         cout << test.top() << endl;
    35         test.pop(); }
    36          
    37     return 0;
    38  
    39 }
    View Code

    3)STL里面默认用的是 vector. 比较方式默认用 operator< , 所以如果你把后面俩个参数缺省的话,优先队列就是大顶堆,队头元素最大。如果要用到小顶堆,则一般要把模板的三个参数都带进去。STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆

     1 #include <iostream>
     2 #include <queue>
     3 #include <cstdlib>
     4 
     5 using namespace std;
     6  
     7 int main(){
     8     
     9     priority_queue<int, vector<int>, greater<int> > q;
    10      
    11     for( int i= 0; i< 10; ++i ) q.push( rand() );
    12     while( !q.empty() ){
    13         cout << q.top() << endl;
    14         q.pop();
    15     }
    16      
    17     return 0;
    18 }
    View Code

       4)对于自定义类型,则必须自己重载 operator< 或者自己写仿函数

     1 #include <iostream>
     2 #include <queue>
     3 #include <cstdlib>
     4 
     5 using namespace std;
     6  
     7 struct Node{
     8     int x, y;
     9     Node( int a= 0, int b= 0 ):x(a), y(b) {} //初始化
    10 };
    11  
    12 bool operator<( Node a, Node b ){
    13     if( a.x== b.x ) 
    14         return a.y> b.y;
    15     else
    16         return a.x> b.x;
    17 }
    18  
    19 int main(){
    20     priority_queue<Node> q;
    21      
    22     for( int i= 0; i< 10; ++i )
    23     q.push( Node( rand(), rand() ) );
    24      
    25     while( !q.empty() ){
    26         cout << q.top().x << ' ' << q.top().y << endl;
    27         q.pop();
    28     }
    29      
    30     return 0;
    31 }
    View Code

       5)自定义类型重载 operator< 后,声明对象时就可以只带一个模板参数。但此时不能像基本类型这样声明priority_queue<Node, vector<Node>, greater<Node> >;原因是 greater<Node> 没有定义,如果想用这种方法定义则可以按如下方式:

     1 #include <iostream>
     2 #include <queue>
     3  
     4 using namespace std;
     5  
     6 struct Node{
     7     int x, y;
     8     Node( int a= 0, int b= 0 ):
     9         x(a), y(b) {}
    10 };
    11  
    12 struct cmp{
    13     bool operator() ( Node a, Node b ){
    14         if( a.x== b.x ) return a.y> b.y;
    15          
    16         return a.x> b.x; }
    17 };
    18  
    19 int main(){
    20     priority_queue<Node, vector<Node>, cmp> q;
    21      
    22     for( int i= 0; i< 10; ++i )
    23     q.push( Node( rand(), rand() ) );
    24      
    25     while( !q.empty() ){
    26         cout << q.top().x << ' ' << q.top().y << endl;
    27         q.pop();
    28     }
    29      
    30     getchar();
    31     return 0;
    32 } 
    View Code

     要注意的是,如果重载cmp,return a > b的形式形成的堆堆顶为最小元素!!

    ------------------------------------------------------------------
    现在的你,在干什么呢?
    你是不是还记得,你说你想成为岩哥那样的人。
  • 相关阅读:
    sql被注入,用友不能建账
    项目总帐金额翻倍
    1)123104科目的余额出现翻倍情况,经调数据库,期初余额已调平,但余额表中的数仍是未调平前的错误数。2)一月结账时提示有一科目119101的总账与个人明细账不平....
    尚有已全部暂估报销的单据未进行处理,不能进行12月的期末处理
    用友U8尚有已全部暂估报销的单据未进行处理,不能进行12月的期末处理
    用sql替换T6工作流中的操作员
    解决win7科迈登录报错RASRDP MODULE已停止工作
    sql2005 64 位 连接 sql2000 32位
    jquery选择器
    深入理解jQuery中$.get、$.post、$.getJSON和$.ajax的用法
  • 原文地址:https://www.cnblogs.com/plumrain/p/stl_priority_queue.html
Copyright © 2011-2022 走看看