许多应用都需要处理有序的元素,但有时,我们不要求所有元素都有序,或是一定要一次就将它们排序,许多情况下,我们会收集这些元素里的最大值或最小值。
这种情况下一个合适的数据结构应该支持两种操作:插入元素、删除最大元素。
优先队列与栈和队列类似,但它有自己的奇妙之处。
在本文中,会讲解基于二叉堆的一种优先队列的经典实现方法(代码没有任何难度,主要是理解思想)。
一、关于堆
1、堆的定义:
数据结构二叉堆能很好地实现优先队列的操作。在二叉堆中,每个元素都要保证大于等于另外两个位置的元素,相应的,这些位置的元素又至少要大于等于数组中的另外两个元素。
将所有元素画成一颗二叉树,就能很容易看出这种结构。

(图示1)
2、堆的算法:
在堆有序的过程中我们会遇到两种情况:
某个节点的优先级上升,我们需要由下至上恢复堆的顺序。
当某个节点的优先级下降,我们需要由上至下恢复堆的顺序。
在排序算法中,我们只通过私有辅助函数来访问元素:
1 private void exch(int i, int j) { 2 Key temp = pq[i]; 3 pq[i] = pq[j]; 4 pq[j] = temp; 5 } 6 7 private boolean less(int i, int j) { 8 return pq[i].compareTo(pq[j]) < 0; 9 }
①、由下至上的堆的有序化(上浮)
1 private void swim(int k) {// 二叉堆 2 while (k > 1 && less(k / 2, k)) { 3 exch(k / 2, k); 4 k = k / 2; 5 } 6 }k/2即为k节点的父节点,当k大于k/2时交换两者,并继续与其父节点比较,直到找到合适的位置。
②、由上至下的堆的有序化(下沉)
1 private void sink(int k) {// 二叉堆 2 while (2 * k <= N) { 3 int j = 2 *

