大根堆与小根堆的理解,如何手写一个堆,以及什么时候用自己手写的堆,什么时候用语言提供堆的api,(二者的区别)
定义
Heap是一种数据结构具有以下的特点:
1)完全二叉树;
2)heap中存储的值是偏序;
Min-heap: 父节点的值小于或等于子节点的值;
Max-heap: 父节点的值大于或等于子节点的值;
用通俗语言来说,大根堆就是每个最大的数字在每个子树的最上方,及大根堆pop值为最大值,小根堆反之
堆的存储
堆的存储一般由数组表示,由于堆的实质就是完全二叉树,所以对于每个i来说(从0开始),左右孩子分别为2i+1,2i+2,父节点为(i-1)/2,
堆的核心操作(手写与语言api均有)
heapinsert与heapify
1.heapinsert:加入一个节点,通过上升的方式,依次进行比较,(上升操作),时间复杂度为o(logN)因为树的深度为logN
swap为交换操作
private void heapInsert(int[] arr, int index) {
while (arr[index] > arr[(index - 1) / 2]) {
swap(arr, index, (index - 1) / 2);
index = (index - 1) / 2;
}
}
2.heapify:弹出根结点之后的,将剩余变成堆的操作(下沉操作),因为弹出根结点后,会将数组最后面的数字顶替为根结点,所以只需将该结点进行下沉操作即可,时间复杂度为o(logN)树的深度为logN
swap为交换操作
/**
*
* @param arr 数组
* @param index 索引
* @param heapSize 堆大小
*/
private void heapify(int[] arr, int index, int heapSize) {
int left = index * 2 + 1;
while (left < heapSize) {
int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
largest = arr[largest] > arr[index] ? largest : index;
if (largest == index) {
break;
<