咱们能够把任意优先队列编程一种排序方法。将全部元素插入一个查找最小元素的优先队列,而后再重复调用删除最小元素的操做来将他们按顺序删除。用无序数组实现的优先队列这么作至关于一次选择排序。用基于堆的优先队列排序至关于我今天要说的——堆排序。java
堆排序能够分为两个阶段:①堆的构造 ②下沉排序算法
堆的构造:①用swim()能够在与NlogN成正比的时间内完成这项操做。只需从左至又遍历数组,②挨个把元素插入到堆中。编程
②用sink()只需少于2N次比较和小于N次交换。显然下沉操做更加高效。将每一个节点下沉排序,即经过此算法可使只有目前节点做为根节点的堆进行有序化,显然数组中N/2以后的节点都不存在新的子叶,故下沉函数从N/2之前从右至左挨个实现当前子堆的有序化,最终可实现整个堆的有序化。数组
下沉排序:将堆中最大元素放到最后,使堆的规模减少一,再循环次步骤,直至堆中不存在元素。缓存
堆排序的代码实现:函数
public static void sort(Comparable [] a) { int N=a.length; for(int k=N/2;k>=1;k--) { //构造堆,即实现堆的有序化 sink(a,k,n); } while(N>1) { exch(a,1,N--); //交换根节点和堆中最后一个元素的位置,即将目前堆中最大的元素放于对的最后 sink(a,1,N); //从新进行堆的有序化 } }
性能:将N个元素排序,堆排序只须要少于(2NlgN+2N)次比较(以及一半次数的交换)。性能
堆排序是咱们所知的惟一可以同时最优地利用空间和时间的方法。code
可是现代系统中应用很少,由于它不多和数组中相邻的元素比较,即没法利用缓存,因此缓存未命中的次数要远高于不少算法。排序
另外一方面它也十分重要,由于它能在插入操做和删除最大元素操做的混合的动态场景中保证对数级别的运行时间。队列