基本概念
堆是一种数据结构,定义为一棵完全二叉树。假如用数组储存堆结构,那么对于某个index为i的节点来说,它的左儿子的index为2*i+1,右儿子为2*i+2。
堆有两种,小根堆和大根堆。对于小根堆,它的每个节点的值都小于该节点左右儿子的值。同理大根堆。
堆的操作
堆化(heapify)
时间复杂度:$O(n)$
表面上看heapify应该为$O(nlogn)$,但是对于在第$h-i$层的节点来说,它最多的shiftdown深度为$i$,shiftdown每一层的复杂度为$O(1)$,而第$h - i$层一共有$2 ^ {h - i} $个节点, 所以整个heapify的时间复杂度为:
$$2^{h-1} \times 1 + 2^{h-2} \times 2 + … + 2^{1} \times {h-1} + h$$
这是一个等比数列,通过将它乘以2,并做差,得到:
$$ 2^{h+1} - 2 - h $$
因为$h = logn$,所以heapify的时间复杂度为$O(n)$。
1 | public class Heap { |
添加
时间复杂度:$O(logn)$
删除
时间复杂度:$O(logn)$
返回堆顶
时间复杂度:$O(1)$
1 | public class minHeap { |
Java 中的堆
在Java中,堆通过优先队列实现,即PriorityQueue。在初始化堆的时候,需要定义堆的大小和排序方式。默认为小根堆。
1 | PriorityQueue<Integer> heap = new PriorityQueue<>(size, new Comparator<Integer>() { |