1. 程式人生 > >堆排序的Java實現、效能分析以及適用場景

堆排序的Java實現、效能分析以及適用場景

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:優先佇列通常用堆排序來實現。