优先队列 C++实现

优先队列:

按键的大小排列的一种数据结构, 用堆实现性能最好,插入和删除操作都可以保证在对数时间内完成, 其中两个重要的操作为:删除最大元素、 插入元素。

堆是一个完全二叉树, 堆中的每一个父节点都比两个子节点大, 一般用数组存放。
若当前节点为k,则它的孩子节点为2k、2k+1, 父节点为 k/2(向下取整)。
堆的两个核心操作为下沉和上浮, pq为数组,代码如下

void sink(int k){
     while(2*k <= N){           //当k有孩子节点时循环
     int j = 2*k;               //令j指向k的左孩子
      //若k有右孩子且右孩子大于左孩子的值, j指向右孩子
     if(j < N && pq[j] < pq[j+1]) j++;
     if(pq[j] < [q[k]) break; //如果孩子节点小于父节点, 下沉操作完成
     swap(pq[j], pq[k]); 
     k = j;                   //孩子节点成为下次循环的父节点, 继续循环。
     }
}
void swim(int k){
     //若当前节点不为根节点并且当前节点大于父节点就交换两个节点。
     while(k > 1 && pq[k] > pq[k/2]){ 
     swap(pq[k], pq[k/2];
     k /= 2;        
   }
}

下沉操作可以实现堆的删除最大元素, 上浮操作可以实现堆的插入元素。
代码如下

删除最大元素的操作:把最大元素与最后一个元素交换位置, 然后对根节点进行下沉操作,使堆重新有序。

int delMax(){
    int m = pq[1];    
    swap(pq[N--], pq[1]);
    sink(1);
    return m;
}

插入操作: 将插入的元素放在最后一个并对其进行上浮操作。

void insert(int v){
     pq[++N] = v;
     swim(N);
}

下面就可以实现优先队列了。

#include<iostream>
using namespace std;
template <class T>
class priority_queue{
    T *pq;
    int N = 0;
    void swim(int k){
        while(k > 1 && pq[k] > pq[k/2]) {swap(pq[k], pq[k/2]); k /= 2;}
    }
    void sink(int k){
        while(2*k <= N){
            int j = 2*k;
            if(j < N && pq[j] < pq[j+1]) j++;
            if(pq[j] < pq[k])break;
            swap(pq[j], pq[k]);
            k = j;
        }
    }
    void swap(int &a, int &b){
        T t = a;
        a = b;
        b = t;
    }
    public:
    priority_queue(int n){pq = new T[N+1];}
    void insert(T v){
        pq[++N] = v;
        swim(N);
    }
    T delMax(){
        T m = pq[1];
        swap(pq[N--], pq[1]);
        sink(1);
        return m;
    }
    T Max(){return pq[1];}
    int size(){return N;}
    bool empty(){return N == 0;}
};
int main(){
    priority_queue<int> q(10);
    q.insert(1);
    q.insert(3);
    q.insert(2);
    cout << q.delMax();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值