一.定义
堆是一颗具有特定性质的二叉树
满足条件
- 非叶子父亲节点一定大于或者小于 叶子子节点
- 是一颗完全二叉树
如
大顶堆
非叶子节点一定大于叶子节点
- a[i] 非叶子节点
- a[2*i+1] 左叶子节点
- a[2i + 2] 右叶子节点
也就是满足 **a[i]>a[2i+1] && a[i] > a[2*i] + 2**
小顶堆
非叶子节点一定小于叶子节点
- a[i] 非叶子节点
- a[2*i+1] 左叶子节点
- a[2i + 2] 右叶子节点
也就是满足 **a[i] < a[2i+1] && a[i] < a[2*i] + 2**
二.堆的插入数据
如下图,图引用 https://zhuanlan.zhihu.com/p/39615266
也就是插入26这个节点 与父节点比较如果比父节点大的话就和父节点交换,再和父亲节点去比较,如果还比父亲节点大 则继续交换 直到到达满足a[i]>a[2i+1] && a[i] > a[2i] + 2 为止
- 假设插入的下标为i 则父节点的下标为 (i-1)*2 或者 (i-1) >>>
实现
大顶堆heapify
此处用数组实现
/**
* 大顶堆
* @param array
*/
public static void maxHeap(int[] array,int length){
int parent = length/2-1;
//从最底层 最右边开始遍历
for(int i=parent;i>=0;i--){
adjustMaxHeap(array,i,length);
}
}
/**
* 调整大顶堆
* @param array
* @param i 调整开始位置 向下调整
* @param length 可以自定义堆调整的实际长度
*/
public static void adjustMaxHeap(int[] array,int i,int length){
int temp = array[i];
for(int j=(2*i+1);j<length;j=2*j+1){
//j代表下一次需要遍历的起始节点
if(j+1<length && array[j] < array[j+1]){
j++;
}
//如果叶子节点存在大于父节点的值 则交换值
if(array[j] > temp){
array[i] = array[j];
//替换下标 继续遍历 小标为maxIndex之后的数据 也就是 2*maxIndex+1
i = j;
}
}
array[i] = temp;
}
小顶堆heapify (和大顶堆类型)
/**
* 小顶堆
* @param array
*/
public static void minHeap(int[] array,int length){
int parent = length/2-1;
for(int i=parent;i>=0;i--){
adjustMinHeap(array,i,length);
}
}
/**
* 调整小顶堆
* @param array
* @param i
* @param length
*/
public static void adjustMinHeap(int[] array,int i,int length){
int temp = array[i];
//k是实际继续调整堆的起点
for(int k=2*i+1;k<length;k=k*2+1){
//右叶子小于左叶子 k右移
if(k+1<length && array[k] > array[k+1]){
k++;
}
if(array[k] < temp){
array[i] = array[k];
//i变为实际开始遍历的下标 也是等待被替换的小标
i = k;
}else {
break;
}
}
array[i] = temp;
}
三.入大顶堆
/**
* 入大顶堆
* @param array
* @param a
* @param index 入堆小标
*/
public static void addMaxHeap(int[] array,int a,int index){
array[index] = a;
adjustMaxHeap(array,(index-1)/2,index+1);
}
/**
* 入小顶堆
* @param array
* @param a
* @param index
*/
public static void addMinHeap(int[] array,int a,int index){
array[index] = a;
adjustMinHeap(array,(index-1)/2,index+1);
}
四.弹出大顶堆
/**
* 弹出大顶堆 堆首和堆尾交换后 重新堆话
* @param array 已经堆化的大顶堆
* @return
*/
public static int popMaxHeap(int[] array){
int pop = array[0];
array[0] = array[array.length-1];
array[array.length-1] = pop;
maxHeap(array,array.length-1);
return pop;
}
五.弹出小顶堆
/**
* 弹出小顶堆 堆首和堆尾交换后 重新堆话
* @param array 已经堆化的小顶堆
* @return
*/
public static int popMinHeap(int[] array){
int pop = array[0];
array[0] = array[array.length-1];
array[array.length-1] = pop;
minHeap(array,array.length-1);
return pop;
}