C++算法(四)之最大优先级队列

来源:互联网 发布:手持云台 知乎 编辑:程序博客网 时间:2024/05/17 02:33

Ps:本文是写了C++排序算法(一)之堆排序之后

(个人觉得这个C++ STL 中的优先队列很有用,所以放于0x0节:
不过为了加深对它的理解,在0x1~0x3节会对它进行一个模拟。
如果只想要会用,看完0x0节即可!)

==================================================

0x0 C++ STL中的priority_queue



priority_queue<Type, Container, Functional>
Type 为数据类型, Container 为保存数据的容器,Functional 为元素比较方式

【STD 手册】:
namespace std {
    template < class T ,
           class Container = vector<T> ,
           class Compare = less <typename Container::value_type> >
    class priority_queue ;
}

【可以看到】:
容器默认是vector,比较方式默认是less,默认比较是operator< ,产生的结果默认是大根堆(最大堆)

【使用方法】:
priority_queue<int> pq1;   //大根堆
priority_queue<int, vector<int>, greater<int> > pq2; //知道如何产生小根堆(最小堆)了吧?
priority_queue<Node> pq3 ;    //自定义结点,大根堆,此时要重载operator<
priority_queue<Node, vector<Node>, cmp > pq4; //自定义结点,小根堆,cmp是自己写的比较函数,因为greater<Node>没定义,重载opreator>没用

【核心函数】:
push() 将一个元素置于priority queue中
top()  返回priority queue中的下一个元素
pop() 从priority queue 中移除一个元素

【代码范例】:
#include <iostream>#include <queue>#include <algorithm>using namespace std;struct Node{    int x,y;    Node(int a=0,int b=0):x(a),y(b){}};bool operator<(Node a,Node b){    if(a.x == b.x) return a.y > b.y;    return a.x > b.x;}struct cmp{    bool operator()(Node a,Node b){        if(a.x == b.x) return a.y < b.y;        return a.x < b.x;    }};int main(){    //////////-----pq1------////////////    cout<<"pq1(大根堆):"<<endl;    priority_queue<int> pq1;    for(int i=0; i<10; i++)    {        pq1.push(rand());    }    while(!pq1.empty())    {        cout<<pq1.top()<<" ";        pq1.pop();    }    cout<<endl;    //////////-----pq2------////////////    cout<<"pq2(小根堆):"<<endl;    priority_queue<int,vector<int>,greater<int> > pq2;    for(int i=0; i<10; i++)    {        pq2.push(rand());    }    while(!pq2.empty())    {        cout<<pq2.top()<<" ";        pq2.pop();    }    cout<<endl;    //////////-----pq3------////////////    //这里就要重载这个operator<    cout<<"pq3(大根堆):"<<endl;    priority_queue<Node> pq3;    for(int i=0; i<10; i++)    {        pq3.push(Node(rand(),rand()));    }    while(!pq3.empty())    {        cout<<"("<<pq3.top().x<<","<<pq3.top().y<<") ";        pq3.pop();    }    cout<<endl;    //////////-----pq4------////////////    //这里重载operator>没用    //因为greate<Node>里面也没有重载    //最好的方法就是自己写个struct cmp    cout<<"pq4(小根堆):"<<endl;    priority_queue<Node,vector<Node>,cmp > pq4;    for(int i=0; i<10; i++)    {        pq4.push(Node(rand(),rand()));    }    while(!pq4.empty())    {        cout<<"("<<pq4.top().x<<","<<pq4.top().y<<") ";        pq4.pop();    }    cout<<endl;    return 0;}



0x1 什么是最大优先级队列


它不是一种普通的先进先出队列(队列是什么?天啊!),它维护的元素有个优先级属性,
不管如何进队列,出列队的都是优先级最大的元素!


0x2 应用在哪里


计算机的分时调度啊
最小生成树的Prim算法
...


0x3 操作有?


INSERT(S,x):将元素x插入到集合S

MAXIMUM(S):返回S中具有最大关键字的元素

EXTRACT-MAX(S):去掉并返回S中的具有最大关键字的元素

INCREASE-KEY(S,xk):将元素x的关键字的值增到k,这里k值不能小于x的原关键字的值


0x4 代码实现


【测试代码】

#include "Priority_Queue.h" #include <iostream>using namespace std;int main(){    //test for Insert()    Priority_Queue pq;    for(int i = 0;i < 5;i++)        pq.insert(rand()%10);    //test for maxNum()    for(int i = 0;i < 5;i++)        cout<<pq.m_pq[i]<<" ";    cout<<endl<<pq.maxNum()<<endl;    //test for increase_key()    pq.increase_key(2,pq.m_pq[2]+15);    for(int i = 0;i < 5;i++)        cout<<pq.m_pq[i]<<" ";    cout<<endl<<pq.maxNum()<<endl;    //test for extract_max()    while(!pq.empty())    {        cout<<pq.extract_max()<<" ";    }    cout<<endl;        return 0;}

【Priority_Queue代码】

#ifndef PRIORITY_QUEUE_H#define PRIORITY_QUEUE_H#include <vector>#include <iostream>using namespace std;class Priority_Queue{    public:        Priority_Queue();        virtual ~Priority_Queue();        //类似 pq.top()        int maxNum()        {            return m_pq.front();        }        //类似 pq.push()        void insert(const int data)        {            m_pq.push_back(data);            make_heap();        }        //类似 pq.top() + pq.pop()        //去掉并返回pq的最大元素        int extract_max()        {            int max = m_pq.front();            swap(m_pq[0],m_pq[m_pq.size()-1]);            m_pq.pop_back();            MaxHeapify(0);            return max;        }        bool empty()        {            if(m_pq.size() == 0)                return true;            else                return false;        }        void increase_key(int i,int key)        {            if(m_pq[i] > key)            {                cout<<"new key is smallor than current key!"<<endl;                return;            }            m_pq[i] = key;            //此时可能会破坏堆性质,需要调整            //不断和父亲交换如果比父亲大的话 m_pq[(i-1)/2] 就是父亲            while( i >= 1 && m_pq[(i-1)/2] < m_pq[i])            {                swap(m_pq[(i-1)/2],m_pq[i]);                i = (i-1)/2;            }        }        void make_heap()        {            for(int i = m_pq.size()/2;i >= 0; i--)            {                MaxHeapify(i);            }        }        void MaxHeapify(unsigned int i)        {            unsigned int left = (i<<1)+1;            unsigned int right = (i<<1)+2;            unsigned int max = i;            if(left < m_pq.size() &&  m_pq[i] < m_pq[left])                max = left;            if(right < m_pq.size() &&  m_pq[max] < m_pq[right])                max = right;            if(max != i)            {                swap(m_pq[i],m_pq[max]);                MaxHeapify(max);            }        }    protected:    public:        vector<int> m_pq;};#endif // PRIORITY_QUEUE_H




原创粉丝点击