標籤:
[演算法說明]
堆排序是對簡單選擇排序的改進
簡單選擇排序是從n個記錄中找出一個最小的記錄,需要比較n-1次。但是這樣的操作並沒有把每一趟的比較結果儲存下來,在後一趟的比較中,有許多比較在前一趟已經做過了,但由於前一趟排序時未儲存這些比較結果,所以後一趟排序時又重複執行了這些比較操作,因而記錄的比較次數較多。
堆是具有下列性質的完全二叉樹:每個結點的值都大於或等於其左右孩子結點的值,稱為大頂堆;或者每個結點的值都小於或等於其左右孩子結點的值,稱為小頂堆。
[演算法思想]
將待排序的序列構造成一個大頂堆。此時,整個序列的最大值就是堆頂的根節點。將它移走(其實就是將其與堆數組的末尾元素交換,此時末尾元素就是最大值),然後將剩餘的n-1個序列重新構造成一個堆,這樣就會得到n個元素中的次最大值。如此反覆執行,就能得到一個有序序列了。
[java實現]
public class HeapSort {public static void main(String[] args) {int[] arr = { 6, 5, 3, 1, 8, 7, 2, 4 };System.out.println("排序之前:");for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}// 堆排序heapSort(arr);System.out.println();System.out.println("排序之後:");for (int i = 0; i < arr.length; i++) {System.out.print(arr[i] + " ");}}/** * 堆排序 */private static void heapSort(int[] arr) { for (int i = arr.length / 2; i >= 0; i--){ // 將待排序的序列構建成一個大頂堆heapAdjust(arr, i, arr.length); }for (int i = arr.length - 1; i > 0; i--) { // 逐步將每個最大值的根節點與末尾元素交換,並且再調整其成為大頂堆swap(arr, 0, i); // 將堆頂記錄和當前未經排序子序列的最後一個記錄交換heapAdjust(arr, 0, i);}}private static void heapAdjust(int[] arr, int i, int n) {int child;int tmp;for (tmp = arr[i]; leftChild(i) < n; i = child) {child = leftChild(i);if (child != n - 1 && arr[child] < arr[child + 1]) {child++;}if (tmp < arr[child]) {arr[i] = arr[child];} else {break;}}arr[i] = tmp;}private static int leftChild(int i) {return 2 * i + 1;}private static void swap(int[] arr, int index1, int index2) {int tmp = arr[index1];arr[index1] = arr[index2];arr[index2] = tmp;}}
[演算法總結]
堆排序時間複雜度:O(nlogn)
堆排序對原始記錄的排序狀態並不敏感,其在效能上要遠遠好過於冒泡、簡單選擇、直接插入排序。
Java排序演算法(五):堆排序