算法思想
堆的概念
堆:通常可以看成是一个完全二叉树的数组。(堆排序实际上是堆中元素的交换,因此可以用数组实现,并且数组的查询和修改效率比较高,能够提高性能)
堆的两种形式:
- 大顶堆:根节点大于左右孩子的节点
- 小顶堆:根节点小于左右孩子的节点
构造堆
1、二叉树堆结构中元素与数组堆结构中元素的对应关系:(大小顶堆一样的)
那么对于某一个节点 index,它的左右孩子在数组中的下标分别为:
- Left=index*2+1
- Right=index*2+2
叶子结点和非叶子节点的区别:
- 非叶子节点的下标<节点个数/2-1
- 叶子节点的下标>节点个数/2-1
2、大顶堆的维护(核心)
自下而上地维护一个大顶堆,使其满足大顶堆的性质:非叶子节点的左右孩子都小于它的根节点
维护分为初始化时大顶堆的维护和初始化后大顶堆的维护:
- 刚开始将待排序数组中的前k个元素复制到堆结构中的数组中,并调用HeapAdjust()方法,从非叶子节点开始,自下而上地维护;
- 而对于新插入的剩下的n-k个元素,只有当元素小于大顶堆的根节点时,才会移除根节点,并将该元素加入大顶堆。因此除了0号元素可能不满足大顶堆的性质外,它的下层的非叶子节点都满足性质,所以**维护的实质是:**维护index=0的情况。
优先队列实现堆排序
优先级队列的元素按照自然排序进行排序,或者根据构造队列时提供的 **Comparator(比较器)**进行排序,具体取决于所使用的构造方法。优先级队列不允许使用 null 元素,依靠自然排序的优先级队列还不允许插入不可比较的对象(这样容易导致 ClassCastException)。
队列的头相当于堆的根节点
构造方法:
a.无 Comparator 参数:默认自然排序,实现小顶堆;
b.传入 Comparator:重写里面的 compare 方法,实现大顶堆。(常用)
PriorityQueue(int initialCapacity)
//使用指定的初始容量创建一个PriorityQueue,并根据自然排序对元素排序
PriorityQueue(int initialCapacity,Comparator<? super E> comparator)
//使用指定的初始容量创建一个PriorityQueue,并根据指定的比较器对元素排序
<