堆的定义
这里说的堆是指二叉堆,二叉堆是完全二叉树或者是近似完全二叉树。
二叉堆满足二个特性:
- 父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
- 每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆
因为堆的本质是完全二叉树,因此
1 | 对于一个结点数为n的堆,其高度为lgn,证明过程可以设高度为h,则n>=2^h-1且n<2^(h+1)-1,即可推导出结果 |
因此插入或者移除一个元素的时间复杂度即为O(lgn)
优先队列
优先队列是一个无界队列,可以按照默认排序或者指定的comparator来排序,本质上仍然是一个堆,注意到这是非线程安全的。
堆的基本操作
往堆中添加元素其实就是要维护堆的属性,这里直接分析Java中优先队列的实现:
siftUpComparable是add的核心实现
1 | private void siftUpComparable(int k, E x) { |
其中
1 | int parent = (k - 1) >>> 1; |