手写堆

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);

以上是关于手写堆的主要内容,如果未能解决你的问题,请参考以下文章

前端面试题之手写promise

数据结构:堆手写

手写堆

2019秋招复习笔试--手写代码

c++手写堆

Luogu [P1334] 瑞瑞的木板(手写堆)