堆Heap

堆本质上是一个完全二叉树,一般分为大根堆和小根堆。
大根堆:父节点的值大于或等于子节点的值
小根堆:父节点的值小于或等于子节点的值

堆的操作

插入

将值插入到堆空余位置,保持完全二叉树,然后开始比较插入值和当前父节点的大小,根据大根堆和小根堆进行节点之间的交换

删除

一般是删除头节点,一般是通过将最后一个节点和头节点交换,然后进行当前头节点的下移,最后删除最后一个节点就可以了

堆的实现

可以理解为将一个数组,变换为一个大根堆或者小根堆,由于是完全二叉树,所以对于一个节点i,那么其子节点就是2i+1和2i+2;为了实现这个结构需要实现前面说的两个操作

堆的初始化

vector<int> h(N); // 堆的数组,数据下标从1开始
int m = 0; // 堆的大小

插入实现

插入后,需要向上移动该节点

void insert(int val)
{
   h[++m] = val;
   up(m);
}

void up(int index)
{
  while(index/2 > 0 && h[index] > h[index/2]) // 大根堆
  {
    swap(h[index], h[index/2]);
    index /= 2;
  }
}

删除实现

将第一个节点,和最后一个节点交换,之后将第一个节点调整顺序

void pop()
{
  if(m <= 1) 
  {
    h.resize(0);
    return;
  }
  h[1] = h[m--];
  down(1);
  h.resize(m);
}
void down(int index)
{
  while(index <= m)
  {
    int cur = index;
    if(index*2 <= m && h[cur] < h[index*2]) cur = index*2; // 与左子节点比较,如果小,则可能变换的下标变为index*2
    if(index*2+1 <= m && h[cur] < h[2*index+1]) cur = index*2+1; //与右子节点比较,如果小,则可能变换的下标变为index*2+1
    if(index == cur) break;
    swap(h[cur],h[index]); //得到右节点,左节点和父节点中最小的位置,实现交换
    index = cur; //移动index为当前下标,继续向下移动
  }
}

作者:XTG111

出处:https://www.cnblogs.com/XTG111/p/18375162

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   XTG111  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示