冷静 清|

艾特玖

园龄:3年11个月粉丝:12关注:7

【数据结构】堆

模拟堆

目的

  1. 插入一个数x
  2. 输出当前集合中的最小值
  3. 删除当前集合的最小值
  4. 删除第k个插入的数
  5. 修改第k个插入的数,将其变为x

实现

struct modheap
{
    int h[N],ph[N],hp[N],idx=0,len=0;
    void heap_swap(int a,int b)
    {
        swap(h[a],h[b]);
        swap(hp[a],hp[b]);
        swap(ph[hp[a]],ph[hp[b]]);
    }
    void down(int x)
    {
        int t = x;
        if(x*2<=len&&h[x*2]<h[t]) t=2*x;
        if(x*2+1<=len&&h[x*2+1]<h[t]) t=2*x+1;
        if(t!=x)
        {
            heap_swap(t,x);
            down(t);
        }
    }
    void up(int x)
    {
        if(x/2&&h[x/2]>h[x]) 
        {
            heap_swap(x/2,x);
            up(x>>1);
        }
    }
    void insert(int x)
    {
        len++,idx++;
        h[len]=x;
        ph[idx]=len,hp[len]=idx;
        up(len);
    }
    int get()
    {
        return h[1];
    }
    void del_mi()
    {
        heap_swap(1,len);
        len--;
        down(1);
    }
    void del_kth(int k)
    {
        int u  = ph[k];
        heap_swap(u,len);
        len--;
        up(u);down(u);
    }
    void mod_kth(int k,int x)
    {
        h[ph[k]]=x;
        up(ph[k]);down(ph[k]);
    }
};

对顶堆

目的

动态维护中位数

实现原理

对顶堆,一个是小根堆,另一个是大根堆。假设 g 是大根堆,l 是小根堆,那么观察下图不难发现,两堆中间的元素,左边都是小于它的,且 g.top() 是小于它的最大值,右边都是大于它的,且 l .top() 是大于它的最小值。

实现

struct midheap
{
    priority_queue<int> g;
    priority_queue<int,vector<int>,greater<int>> l;
    void insert(int x)
    {
        if(!g.size()||x<g.top()) g.push(x);
        else l.push(x);
        if(g.size()>l.size()+1) l.push(g.top()),g.pop();
        if(l.size()>g.size()+1) g.push(l.top()),l.pop();
    }
    //若出现偶数个,且中间两个不同的情况,则该get获得的是较大的
    //若想得到较小的,则将>改为>=
    int get()
    {
        return g.size() > l.size() ? g.top() : l.top();
    }
};

可删除堆

目的

可以完成删除堆内指定元素。

实现原理

我们建一个临时堆,如果要删除哪个元素,就把哪个元素压入临时堆,然后待此元素和正常堆的堆顶元素相同时(即两个堆顶一样),就同时pop掉。

实现

//可删除堆
struct popheap
{
    priority_queue<int> _add,_del;//其中的方向要相同,可以使大根堆也可以是小根堆
    int size()
    {
        while(!_add.empty()&&!_del.empty()&&_add.top()==_del.top()) _add.pop(),_del.pop(); 
        return _add.size();
    }
    int get()
    {
        while(!_add.empty()&&!_del.empty()&&_add.top()==_del.top()) _add.pop(),_del.pop(); 
        return _add.top();
    }
    void add(int x)
    {
        _add.push(x);
    }
    void del(int x)
    {
        _del.push(x);
    }
};

本文作者:艾特玖

本文链接:https://www.cnblogs.com/aitejiu/p/16700945.html

版权声明:本作品采用艾特玖许可协议进行许可。

posted @   艾特玖  阅读(19)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起