1. 程式人生 > >排序演算法之堆排序

排序演算法之堆排序

堆排序

【1】堆排序的思想

        堆排序的思想是指利用堆資料結構所設計的一種資料排序演算法。

        堆:堆是一種特殊的完全二叉樹,最大堆的特點是它的結點的值總是不小於它的父節點的值(也就是說其父節點的值總是大於它的子節點的值),總是一顆完全二叉樹結構。

【2】堆排序過程

A:有輸入的無序陣列構成一個完全二叉樹結構

B:先由此完全二叉樹構成一個最大堆,作為初始堆(一直交換查詢找到最大值放到根節點)

C:將堆頂元素和堆尾的元素交換(此時已經找出了最大值)

D:將堆尾元素從堆中撇開,剩下的的堆尺寸減一,此時的新堆繼續構成一個最大堆

E:一直重複BCD,直到堆的元素只剩一個

【3】堆的資料結構是陣列

【4】堆排序的穩定性:不穩定,發生在在堆頂元素和其它元素進行交換的時候

【5】堆排序的時間複雜度:O(nlogn)

     剛開始建堆的時間複雜度是O(n)

     在建立新堆並向下進行堆調整的時候,時間複雜度是O(logn)

堆排序程式碼如下:

package Collection;

import java.util.Arrays;
public class HeapSort {
    public static void main(String[] args) {
        int[] arr={5,2,9,4,7,6,1,3,8};
        int n=arr.length;
        heapsort(arr,n); //呼叫堆排序函式
        System.out.println(Arrays.toString(arr));
    }
    public static void heapsort(int[] arr, int n){
        int heap_size=buildheap(arr,n);//建立一個最大堆
        while(heap_size>1){      //當堆內元素個數>1的時候
            //這步操作很可能把後面元素的穩定性打亂,因此堆排序是不穩定的排序演算法
            Swap(arr,0,-- heap_size);//將堆頂的元素和堆的最後一個元素互換(此時交換後的最後一個元素就是這個堆裡的最大元素)
            heapify(arr,0,heap_size);//在出過最後一個元素(最大值)之外重新排序(遞迴呼叫)
        }
    }
    public static int buildheap(int[] arr, int n){
        int heap_size=n;
        for(int i=heap_size/2-1;i>=0;i--)
            //從最後一個非葉子結點開始向下進行堆調整
            heapify(arr,i,heap_size);
        return heap_size;
    }
    public static void heapify(int[] arr, int i, int size){
        int left_child=2*i+1;//第i結點的左孩子結點
        int right_child=2*i+2;
        int max=i;
        //接下來找出此節點,此節點的左孩子,此節點的右孩子這三者之間誰最大
        if(left_child<size&&arr[left_child]>arr[max])
            max=left_child;
        if(right_child<size&&arr[right_child]>arr[max])
            max=right_child;
        if(max!=i)
        {
            Swap(arr,i,max);//將最大值和當前結點交換
            heapify(arr,max,size);//遞迴:從當前結點向下調整
        }
    }
    public static void Swap(int[] arr, int x, int y){
        int temp=arr[x];
        arr[x]=arr[y];
        arr[y]=temp;
    }
}