• [算法系列之四]优先级队列


    【概念】

    优先级队列,顾名思义。就是一种依据一定优先级存储和取出数据的队列。它能够说是队列和排序的完美结合体。不仅能够存储数据。还能够将这些数据依照我们设定的规则进行排序。

    优先级队列是堆的一种常见应用。有最大优先级队列(最大堆)和最小优先级队列(最小堆)。优先级队列是一种维护有一组元素构成的集合S的数据结构。

    【优先队列支持的基本运算】

    1. //建立一个保存元素为int的优先级队列,事实上是建了一个小顶堆  
    2. //可是请特别注意这种建的堆默认是大顶堆,即我们从堆顶去的元素是整个堆中元素最大的。  
    3.   
    4. priority_queue<int> Heap;  
    5.   
    6. //能够这样建一个表示小顶堆的优先级队列  
    7.   
    8. priority_queue<int , vector<int>, greater<int> > Heap;  
    9.   
    10. //将元素x放入优先级队列中  
    11.   
    12. Heap.push(x);  
    13.   
    14. //取出优先级队列第一个元素(堆顶元素),保存在x中  
    15.   
    16. int x = Heap.top();  
    17.   
    18. //弹出堆顶元素,取出后堆会自己主动调整为一个最小堆(最大堆)  
    19.   
    20. Heap.pop();  
    21.   
    22. //推断是否为空  
    23.   
    24. Heap.empty();  
    25.   
    26. //头文件  
    27.   
    28. #include<queue>  

    【原理】

    priority_queue调用 STL里面的 make_heap(), pop_heap(), push_heap() 算法实现,也算是堆的第二种形式。


    用make_heap(), pop_heap(), push_heap() 简单实现一个最大优先级队列

    /*********************************
    *   日期:2015-01-06
    *   作者:SJF0115
    *   题目: 简单实现最大优先级队列
    *   博客:
    **********************************/
    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    //简单实现最大优先级队列
    template<typename T>
    class priority_queue{
    private:
        // 数据
        vector<T> data;
    public:
        // 进队列
        void push(T val){
            data.push_back(val);
            push_heap(data.begin(),data.end());
        }
        // 出队列
        void pop(){
            pop_heap(data.begin(),data.end());
            data.pop_back();
        }
        // 头元素
        T top(){
            return data.front();
        }
        // 大小
        int size(){
            return data.size();
        }
        // 是否为空
        bool empty(){
            return data.empty();
        }
    };
    
    int main(){
        priority_queue<char> heap;
        heap.push('5');
        heap.push('4');
        heap.push('3');
        heap.push('9');
        heap.push('6');
        while(!heap.empty()){
            cout<<heap.top()<<endl;
            heap.pop();
        }//while
    }
    
    

    STL里面的 priority_queue 写法与此相似,仅仅是添加了模板及相关的迭代器什么的。 

    priority_queue 对于基本类型的用法相对简单。

    他的模板声明带有三个參数:
    priority_queue<Type, Container, Functional>
    当中Type 为数据类型, Container 为保存数据的容器,Functional 为元素比較方式。
    Container 必须是用数组实现的容器。比方 vector, deque 但不能用 list.
    STL里面默认用的是 vector. 比較方式默认用 operator< , 所以假设你把后面俩个參数缺省的话,
    优先队列就是大顶堆,队头元素最大。

    #include <iostream>
    #include <queue>
    using namespace std;
    
    int main(){
        priority_queue<char> heap;
        heap.push('5');
        heap.push('4');
        heap.push('3');
        heap.push('9');
        heap.push('6');
        // 输出最大优先级队列
        while(!heap.empty()){
            cout<<heap.top()<<endl;
            heap.pop();
        }//while
    }

    假设要用到小顶堆。则一般要把模板的三个參数都带进去。
    STL里面定义了一个仿函数 greater<>,对于基本类型能够用这个仿函数声明小顶堆

    #include <iostream>
    #include <queue>
    using namespace std;
    
    int main(){
        // 最小优先级队列
        priority_queue<char,vector<char>,greater<char> > heap;
        heap.push('5');
        heap.push('4');
        heap.push('3');
        heap.push('9');
        heap.push('6');
        // 输出最大优先级队列
        while(!heap.empty()){
            cout<<heap.top()<<endl;
            heap.pop();
        }//while
    }

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

    【自己定义优先级】

    重载 operator<

    1. #include<iostream>  
    2. #include<stdio.h>  
    3. #include<queue>  
    4. using namespace std;  
    5.   
    6. struct Node    
    7. {    
    8.     //值  
    9.     int value;  
    10.     //编号  
    11.     int key;    
    12.     //重载操作符  
    13.     friend bool operator < (Node node1,Node node2)    
    14.     {      
    15.         //最大优先队列  
    16.         return node1.value < node2.value;    
    17.     }  
    18.     /* 
    19.     不要重载这个'>'仅仅重载'<' 
    20.     friend bool operator > (Node node1,Node node2)   
    21.     {   
    22.         return node1.value > node2.value;   
    23.     }  
    24.     */  
    25. };  
    26.   
    27. struct Node2    
    28. {    
    29.     //值  
    30.     int value;  
    31.     //编号  
    32.     int key;    
    33.     //重载操作符  
    34.     friend bool operator < (Node2 node1,Node2 node2)    
    35.     {      
    36.         //最小优先队列  
    37.         return node1.value > node2.value;    
    38.     }  
    39. };  
    40.   
    41. int main(){  
    42.     int i;  
    43.     //实例一 结构体1  
    44.     Node b[5];  
    45.     b[0].value = 6; b[0].key = 1;   
    46.     b[1].value = 9; b[1].key = 2;   
    47.     b[2].value = 2; b[2].key = 3;   
    48.     b[3].value = 8; b[3].key = 4;   
    49.     b[4].value = 1; b[4].key = 5;   
    50.     //最大优先队列  
    51.     priority_queue<Node> Heap;  
    52.     //入队列  
    53.     for(i = 0;i < 5;i++){  
    54.         Heap.push(b[i]);  
    55.     }  
    56.     printf("最大优先队列: ");  
    57.     //出队列  
    58.     for(i = 0;i < 5;i++){  
    59.         printf("key:%d value:%d ",Heap.top().key,Heap.top().value);  
    60.         Heap.pop();  
    61.     }  
    62.     //实例二 结构体2  
    63.     Node2 b2[5];  
    64.     b2[0].value = 6; b2[0].key = 1;   
    65.     b2[1].value = 9; b2[1].key = 2;   
    66.     b2[2].value = 2; b2[2].key = 3;   
    67.     b2[3].value = 8; b2[3].key = 4;   
    68.     b2[4].value = 1; b2[4].key = 5;   
    69.     //最大优先队列  
    70.     priority_queue<Node2> Heap2;  
    71.     //入队列  
    72.     for(i = 0;i < 5;i++){  
    73.         Heap2.push(b2[i]);  
    74.     }  
    75.     printf("最小优先队列: ");  
    76.     //出队列  
    77.     for(i = 0;i < 5;i++){  
    78.         printf("key:%d value:%d ",Heap2.top().key,Heap2.top().value);  
    79.         Heap2.pop();  
    80.     }  
    81.     return 0;  
    82. }  



    注意:

    1. struct Node    
    2. {    
    3.     //值  
    4.     int value;  
    5.     //编号  
    6.     int key;    
    7.     friend bool operator > (Node node1,Node node2)    
    8.     {    
    9.         return node1.value > node2.value;    
    10.     }   
    11. };  

    这样会报错。由于标准库默认使用元素类型的<操作符来确定它们之间的优先级关系。


    自己定义类型重载 operator< 后,声明对象时就能够仅仅带一个模板參数。
    但此时不能像基本类型这样声明priority_queue<Node, vector<Node>, greater<Node> >;
    原因是 greater<Node> 未定义。假设想用这样的方法定义则能够按例如以下方式:

    #include <iostream>
    #include <queue>
    using namespace std;
    
    struct Node{
        int value;
        int key;
        Node(int x,int y):key(x),value(y){}
    };
    
    struct cmp{
        bool operator()(Node a,Node b){
            if(a.key == b.key){
                return a.value > b.value;
            }
            return a.key > b.key;
        }
    };
    
    int main(){
    
        priority_queue<Node,vector<Node>,cmp> heap;
        Node node0(5,6);
        Node node1(3,3);
        Node node2(2,4);
        Node node3(2,3);
        Node node4(1,3);
    
        heap.push(node0);
        heap.push(node1);
        heap.push(node2);
        heap.push(node3);
        heap.push(node4);
    
        while(!heap.empty()){
            Node node = heap.top();
            cout<<"Key->"<<node.key<<" Value->"<<node.value<<endl;
            heap.pop();
        }//while
    }
    
    



    详细实例:点击打开链接

                       看病要排队

                       搬水果

  • 相关阅读:
    自定义类型百度地图之自定义地图类型详解
    电话文本android(3)_拨打电话操作
    检查运行IIS 5.1 使用出现server application error解决方法
    function运行令人吐血的IE JS兼容性问题。。。
    组件设置window2008 64位系统无法调用Microsoft.Office.Interop组件进行文件另存的解决办法
    api时间转换VarDateFromStr,VariantTimeToSystemTime
    C与CPP文件的区别
    OpenSSL 使用指南
    Pascal保留字/关键字列表
    windbg 启动参数,常用命令
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5260736.html
Copyright © 2020-2023  润新知