手写堆
Posted codertea
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写堆相关的知识,希望对你有一定的参考价值。
手写堆
算法思想
- 堆是一颗完全二叉树
- STL里的堆就是优先队列priority_queue
- 用一维数组存储
- 下标一定是从1开始,避免0的左儿子2x还是0的冲突
- 核心操作:down(x)下移节点 up(x)上移节点
- 插入一个数 heap[++size] = x; up(size);
- 求集合当中的最小值 heap[1];
- 删除最小值 heap[1] = heap[size]; size--; down(1);
- 删除任意一个元素 heap[k] = heap[size]; size--; down(k); up(k);
- 修改任意一个元素 heap[k] = x; down(k); up(k);
代码实现
int h[N],siz;
//这两个数组存映射关系 ph[k]=i表示第k个插入的数对应堆中的编号为i
//hp[i] = k表示堆中编号为i的点是第k个插入的数 k从1开始
//一般用到的堆不需要复杂的交换 不需要存储映射
int ph[N],hp[N];
//节点交换函数 同时要修改映射关系
void heap_swap(int a,int b)
{
swap(ph[hp[a]],ph[hp[b]]);
swap(hp[a],hp[b]);
swap(h[a],h[b]);
}
void down(int u)
{
//t是三个里面最小值的编号
int t = u;
if((u * 2) <=siz && h[u*2] < h[t]) t = u *2;
if((u * 2 + 1) <= siz && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
if(u != t)
{
heap_swap(u,t);
down(t);
}
}
void up(int u)
{
while(u / 2 && h[u / 2] > h[u])
{
heap_swap(u / 2, u);
u /= 2;
}
}
for(int i=1;i<=n;i++) cin>>h[i];
siz = n;
//O(n)建堆
for(int i=n/2;i;i--) down(i);
以上是关于手写堆的主要内容,如果未能解决你的问题,请参考以下文章