堆
堆本质上是一个完全二叉树,一般分为大根堆和小根堆。
大根堆:父节点的值大于或等于子节点的值
小根堆:父节点的值小于或等于子节点的值
堆的操作
插入
将值插入到堆空余位置,保持完全二叉树,然后开始比较插入值和当前父节点的大小,根据大根堆和小根堆进行节点之间的交换
删除
一般是删除头节点,一般是通过将最后一个节点和头节点交换,然后进行当前头节点的下移,最后删除最后一个节点就可以了
堆的实现
可以理解为将一个数组,变换为一个大根堆或者小根堆,由于是完全二叉树,所以对于一个节点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为当前下标,继续向下移动
}
}
标签:index,大根堆,int,插入,二叉树,Heap,节点
From: https://www.cnblogs.com/XTG111/p/18375162