【数据结构】堆
堆
模拟堆
目的
- 插入一个数
x
- 输出当前集合中的最小值
- 删除当前集合的最小值
- 删除第
k
个插入的数 - 修改第
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);
}
};
分类:
数据结构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步