1. 程式人生 > >排序演算法(5)堆排序

排序演算法(5)堆排序

一:基本思想

堆排序是利用堆(一種近似完全二叉樹的結構)這種資料結構設計的一種排序演算法

(1)由輸入的無序陣列構造一個最大堆,作為初始的無序區

(2)把堆頂元素(最大值)和堆尾元素進行互換

(3)把堆的尺寸縮小1,並呼叫heapify(A,0)從新的堆頂元素開始進行堆調整

(4)重複步驟(2),直到堆的尺寸為1

二.概覽

分類:內部比較排序

資料結構:陣列

最差時間複雜度:O(nlogn)

最優時間複雜度:O(nlogn)

平均時間複雜度:O(nlogn)

所需輔助空間:O(1)

穩定性:不穩定(不穩定發生在棧頂元素與a[i]交換的時候)

               比如序列:{ 95, 7, 5 },堆頂元素是9,堆排序下一步將9和第二個5進行交換,得到序列 { 

55, 7, 9 },再進行堆調整得到{ 7, 55, 9 },重複之前的操作最後得到{ 55, 7, 9 }從而改變了兩個5的相對次序。

三.程式碼實現

public class Heap {
    //交換函式
    public static void Swap(int A[], int i, int j)
    {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
    //建堆
    public static int BuildHeap(int a[]){
        int heap_size = a.length;
        for (int i = heap_size/2-1;i >=0;i--){
            heapify(a,i,heap_size );
        }
        return heap_size;
    }
    //堆調整
    public static void heapify(int a[],int i,int size){
        int left_child = 2*i +1;  //左孩子索引
        int right_child = 2*i + 2; //右孩子索引
        int max = i;
        if(left_child<size && a[left_child]>a[max]){
            max = left_child;
        }
        if(right_child<size && a[right_child]>a[max]){
            max = right_child;
        }
        if (max != i){
            Swap(a, max, i); //把當前結點和它的最大子結點進行互換
            heapify(a, max, size);//遞迴呼叫,繼續從當前結點向下調整(注意下是指根)
        }
    }
    //堆排序
    public static void sort(int a[]){
        //建立一個大堆
        int heap_size = BuildHeap(a);
        while (heap_size > 1){ // 大於1表示未完成排序
            //將堆頂元素與最後一個元素交換,並從堆中去掉最後一個元素
            //此處的交換很可能把後面的元素的穩定性打亂,所以堆排序不是穩定的排序
            Swap(a, 0, --heap_size);
            //從新的堆頂元素開始向下調整,時間複雜度o(logn)
            heapify(a, 0, heap_size);
        }
    }
    
}