1.堆是什么?
堆是一颗数组存储的完全二叉树,数组存储元素下标从1开始,如果该完全二叉树规定父元素大于左右孩子,就是最大堆,反之则是最小堆。
2.堆的基础函数
1.前置条件:
h数组是存储堆的数组,size是堆中的最后一个元素的下标,如果为0表示当前堆无元素
2.up(idx)
1.含义 :将数组下标为idx的值在堆中上浮
2.代码:以最大堆为例
//假设当前元素最大 与父亲元素对比
if(h[idx/2]<h[idx]){//比父亲元素大
//交换,也就是上浮
swap(idx/2,idx);
//当前元素已经上浮到idx/2,并且还有可能上浮,递归继续
up(idx/2)
}
//父亲元素大于当前元素,当前元素不操作,不上浮
3.down(idx)
1.含义 :将数组下标为idx的值在堆中下沉
2.代码
//假设当前元素是最大的
int max_idx = idx;
//左孩子存在 将当前元素与左孩子相比
if(idx*2<=size && h[idx*2]>h[max_idx])max_idx=idx*2
//右孩子存在 将当前元素与右孩子相比
if(idx*2+1<=size && h[idx*2+1]>h[max_idx])max_idx=idx*2+1
//当前元素不是最大的,则要下沉
if(max_idx!=idx){
//交换 下沉
swap(max_idx,idx);
//下沉之后 还有可能下沉
down(max_idx)
}
//否则是最大的,不操作
4.建堆
时间复杂度O(n)
思路:从堆中最后一个有孩子的元素(size/2)开始下沉
for(int i = size/2 ; i ;i--){
down(i)
}
3.堆有哪些操作?
1.求最大值/最小值(查)
思路:数组的第一个数就是堆顶最大或最小值
h[1]
2.插入一个值(增)
思路:将数直接插到数组末尾,然后让数组最后一个元素up
h[++size]=x;
up(size);
3.删除任意位置的值(删)
思路:用最后一个元素直接顶替要删除位置的元素,并且size--,然后直接上浮一遍删除位置的元素和下沉一遍,反之只会执行其中一个操作。
h[i] = h[size--];
down(i);
up(i);
4.修改任意位置的值(改)
思路:修改该位置的元素,然后直接上浮一遍和下沉一遍,反之只会执行其中一个操作。
h[i]=x;
down(i);
up(i);