堆排序的Java實現、效能分析以及適用場景
阿新 • • 發佈:2019-02-18
1.堆排序的Java實現:
程式碼如下:
package com.zm.testSort;
/**
* 堆排序
* @author zm
*/
public class HeapSort {
public static void getHeapSort(int[] a) {//堆排序
int n = a.length;
if(a == null || n == 1) {
return;
}
buildMaxHeap(a, n);//呼叫構建最大堆方法,構建一個最大堆
swap(a, 0, n-1 );//交換堆頂元素和堆尾元素,將最大元素置於陣列尾端
for(int len = n-1; len > 1; len--) {//此時需比較的陣列長度為n-1,由於此時除了堆頂元素之外,其他元素都符合最大堆,因此只需每次調整堆頂元素
adjustDown(a, 0, len);//0代表堆頂元素,len代表需比較的陣列部分長度
swap(a, 0, len-1);//交換需比較的陣列部分的堆頂元素和堆尾元素
}
}
public static void buildMaxHeap(int[] a, int length) {//構建最大堆
int k = (length -2)/2;//獲取堆尾元素的父節點的索引
for(; k >=0; k--) {//由該索引開始,從右往左,從下到上,依次調整
adjustDown(a, k, length);//k表示當前(非葉子節點)父節點的索引
}
}
public static void adjustDown(int[] a, int k, int length) {//調整當前節點與它的所有子節點,構建子最大堆
int temp = a[k];
for(int i = 2*k+1 ; i < length; i = 2*i+1) {//i為父節點的左子節點
if((i+1)<length) {//如果有右子節點
if(a[i] < a[i+1]) {//如果右子節點比左子節點大
i++;
}
}
if(temp < a[i]) {//如果父節點小於左右子節點中的最大者
a[k] = a[i];
k = i;//移到子節點中的大著節點上
}else{
break;
}
}
a[k] = temp;
}
public static void swap(int[] a, int b, int c) {
int temp = a[b];
a[b] = a[c];
a[c] = temp;
}
public static void main(String[] args) {
int[] a = {3, 5, 1, 2, 6, 4, 7, 11, 23, 44, 3, 34, 8, 23, 6, 9};
getHeapSort(a);
System.out.print("堆排序:");
for(int i = 0; i < a.length; i++) {
System.out.print(a[i] + " ");
}
}
}
2.堆排序的效能分析:
時間複雜度:
1. 最好情況:O(nlog2(n))
2. 平均情況:O(nlog2(n))
3. 最壞情況:O(nlog2(n))
空間複雜度:O(1)
穩定性:不穩定(相同元素的相對位置會改變)
3.適用場景
3.1:若n較大,則應採用時間複雜度為O(nlog2(n))的排序方法:快速排序、堆排序或歸併排序。
快速排序是目前基於比較的內部排序中被認為是最好的方法,當待排序的關鍵字是隨機分佈時,快速排序的平均時間最短;
堆排序所需的輔助空間少於快速排序,並且不會出現快速排序可能出現的最壞情況。這兩種排序都是不穩定的。
3.2:優先佇列通常用堆排序來實現。