资料:https://blog.csdn.net/guoweimelon/article/details/50904346
但是它的最大堆删除部分的代码有问题,详见链接里的评论区
定义
堆首先必须是一棵完全二叉树
最大堆:完全二叉树,父节点的值不小于子节点的值
最小堆:完全二叉树,父节点的值不大于子节点的值
用数组存储上图所示的最大堆
对于下标为
i
(
1
≤
i
≤
n
)
i (1 \leq i \leq n)
i(1≤i≤n)的节点:
父节点:
i
/
2
i/2
i/2,若
i
=
1
i=1
i=1,则i是根节点
左子节点:2i,如果
2
i
>
n
2i > n
2i>n,则不存在左子节点
右子节点:2i+1,如果
2
i
+
1
>
n
2i+1 > n
2i+1>n,则不存在右子节点
最大堆的插入:时间复杂度O(logn)
肯定在数组末尾加入该数字,然后和父节点进行比较,balabala,也就是节点上浮操作。
最大堆的删除:时间复杂度O(logn)
删除根节点元素,用数组的最后一个元素来顶替,然后进行节点下沉
最大堆的创建:
方法一:可以通过最大堆的插入算法进行构建,即从空堆开始,依次插入数字。该方法的时间复杂度为O(n log n)
方法二:将时间复杂度降低到O(n),先将所有数据放入,然后逐个调整
struct MaxHeap{
int heap[100];
int currentSize=0;
int maxSize=100;
// 最大堆的创建,采用方法二
void HeapInit(int a[],int n){
currentSize = n;
for(int i=0;i<n;i++)
heap[i] = a[i];
for(int i= (currentSize-2)/2; i>=0; i--){
SiftDown(i);
}
}
void SiftDown(int index){
int cur = index;
int son = 2*index+1;
int tmp = heap[index];
while(son < currentSize){
if(son<currentSize-1 && heap[son]<heap[son+1])
son++;
if(tmp < heap[son]){
heap[cur] = heap[son];
cur = son;
son = 2* cur + 1;
}else
break;
}
heap[cur] = tmp;
}
// 插入一个元素
void HeapInsert(int value){
if(currentSize == maxSize) return;
currentSize++;
int index = currentSize-1;
while(index>0){
if( heap[(index-1)/2] >= value) break;
heap[index] = heap[(index-1)/2];
index = (index-1)/2;
}
heap[index] = value;
}
// 删除一个元素
int HeapDelete(){
if(currentSize==0) return -1;
int maxValue = heap[0];
heap[0] = heap[currentSize-1];
currentSize--;
SiftDown(0);
return maxValue;
}
};