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

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,x k) :将元素 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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值