1、引言2、圖解堆排序(heapsort)3、java代碼實現及時間複雜度分析4、總結html
優先隊列能夠用於以O(NlogN)時間排序,正如上一篇的求解topK問題中用到的思想同樣,這種思想就是堆排序(heapsort)。java
對二叉堆不瞭解的能夠看看圖解優先隊列(堆)算法
咱們從數組下標0開始,不像二叉堆從數組下標1開始。數組
public class Heapsort {
public static void main(String[] args) {
Integer[] integers = {7, 1, 13, 9, 11, 5, 8};
System.out.println("原序列:" + Arrays.toString(integers));
heapsort(integers);
System.out.println("排序後:" + Arrays.toString(integers));
}
public static <T extends Comparable<? super T>> void heapsort(T[] a) {
if (null == a || a.length == 0) {
throw new RuntimeException("數組爲null或長度爲0");
}
//構建堆
for (int i = a.length / 2 - 1; i >= 0; i--) {
percDown(a, i, a.length);
}
//deleteMax
for (int i = a.length - 1; i > 0; i--) {
swapReferences(a, 0, i);
percDown(a, 0, i);
}
}
/**
* 下濾的方法
*
* @param a:待排序數組
* @param i:從哪一個索引開始下濾
* @param n :二叉堆的邏輯大小
* @param <T>
*/
private static <T extends Comparable<? super T>> void percDown(T[] a, int i, int n) {
int child;
T tmp;
for (tmp = a[i]; leftChild(i) < n; i = child) {
child = leftChild(i);
if (child != n - 1 && a[child].compareTo(a[child + 1]) < 0) {
child++;
}
if (tmp.compareTo(a[child]) < 0) {
a[i] = a[child];
} else {
break;
}
}
a[i] = tmp;
}
private static int leftChild(int i) {
return 2 * i + 1;
}
/**
* 交換數組中兩個位置的元素
*
* @param a:目標數組
* @param index1 :第一個元素下標
* @param index2 :第二個元素下標
* @param <T>
*/
private static <T> void swapReferences(T[] a, int index1, int index2) {
T tmp = a[index1];
a[index1] = a[index2];
a[index2] = tmp;
}
}
//輸出結果
//原序列:[7, 1, 13, 9, 11, 5, 8]
//排序後:[1, 5, 7, 8, 9, 11, 13]
時間複雜度:buildHeap使用O(N)的時間,元素下濾須要O(logN),須要下濾N-1次,因此總共須要O(N+(N-1)logN) = O(NlogN)。從過程能夠看出,堆排序,無論最好,最壞時間複雜度都穩定在O(NlogN)。app
空間複雜度:使用自身存儲,無疑是O(1)。ui
本篇經過畫圖,說明堆排序的過程,清晰明瞭知道堆排序先通過堆序化,再經過deleteMax進行排序。其空間複雜度是O(1),時間複雜度穩定在O(NlogN)。spa