HeapSort 堆排序
0. 前言
本文继续分析另一个很重要的高效排序算法——堆排序。不过,在此之前,需要先引入堆和优先队列的概念,这是堆排序的基础。
1.优先队列(Priority Queue)
基本概念
顾名思义,优先队列是由队列演变而来的,包含最基本的插入和删除操作。优先队列的插入规则与队列一致,是插入(添加)到队列的末尾;删除规则比较特殊,是删除(在指定规则中)优先级最高的项。
(最大项)优先队列API如下:
public class MaxPQ<Key extends Comparable<Key>>{
MaxPQ() //构造函数
MaxPQ(Key[] a) //构造函数
void insert(Key v) //插入项、添加项
Key delMax() //删除最大值
boolean isEmpty() //判空
Key max() //查找最大值
int size() //查询长度
}
简单应用
想象一个场景:从总数为N的列表中个找出最大的M个项。
方法一:将N列表排序(使用快速排序或者归并排序,从大到小排),然后选择前M项即可。
方法二:使用优先队列,当队列大小达到M时,开始将最小值出队。
方法二的代码如下:
//MinPQ是alg4提供的最小优先队列API
MinPQ<Transaction> pq = new MinPQ<Transaction>();
while (StdIn.hasNextLine()){
String line = StdIn.readLine();
Transaction item = new Transaction(line);
pq.insert(item);
//当队列长度达到M时,每读取一个数字入队后,就将最小值删除
if (pq.size() > M)
pq.delMin();
}
方法一与方法二的对比
实现方法
优先队列可以使用有序数组或者无序数组来实现。使用有序数组时,每次插入都要与数组中原来的项比较,然后插入适当的位置;每次删除只需删除数组最后一项。使用无序数组时,每次插入时插入到数组的最后一项;每次删除时要查找出数组中优先度最高的项,然后与最后一项交换,删除最后一项。
以下是无序数组的实现方式
public class UnorderedMaxPQ<Key extends Comparable<Key>>{
private Key[] pq; // 定义无序数组
private int N; // 定义数组长度
public UnorderedMaxPQ(int capacity){
pq = (Key[])