Java排序演算法 [堆排序]
阿新 • • 發佈:2019-02-04
package cn.com.dom4j.sort; import java.util.Arrays; public class Test2 { /** * 堆排序 */ public static <AnyType extends Comparable<? super AnyType>> void heapSort(AnyType[] a) { // buildHeap for (int i = a.length / 2; i >= 0; i--) { // 將陣列值按初始順序放入堆中, 從根節點執行下濾操作將構建一個堆 percolateDown(a, i, a.length); } // deleteMax for (int i = a.length - 1; i > 0; i--) { // 在構建了一個 max堆後, 將根節點與最後一個元素互換, 同時將堆的大小 -1, 調整位置, 再次實現堆序 // 這樣每互換一次, 最大的元素就會放在堆的後面 (已經從堆中刪除, 不屬於堆了), 堆後面的元素會保持順序, 直到堆中只剩一個元素為止 swap(a, 0, i); percolateDown(a, 0, i); } } /** * 下濾操作: 調整某個節點的位置, 以保持堆序 * @param a 待排序序列 * @param i 要調整的節點在陣列中的索引 * @param n 堆的大小 (堆中元素個數) */ private static <AnyType extends Comparable<? super AnyType>> void percolateDown(AnyType[] a, int i, int n) { int child; AnyType tmp; // tmp記錄被調整元素的值, i的值隨 child不斷改變, 直到比較完所有的子節點 (leftChild(i) < n) 為止 for (tmp = a[i]; leftChild(i) < n; i = child) { child = leftChild(i); // child == n - 1時, 其左子節點為堆的最後一個元素, 沒有右節點, 無須比較 // 將該節點與其左右節點比較, 記錄其中最小的節點的索引 if (child != n - 1 && a[child].compareTo(a[child + 1]) < 0) { child++; } // 將需要被調整和節點與其子節點進行比較, 如果小於子節點, 當前節點的值替換為子節點的值 (注意不是交換) if (tmp.compareTo(a[child]) < 0) { a[i] = a[child]; } else { break; } } // 找到合適的位置後, 直接賦值來避免多餘的交換操作 a[i] = tmp; } /** * 獲取某個節點的左子節點在陣列中的索引, 因為是從 0開始的, 所以要 +1 */ private static int leftChild(int i) { return 2 * i + 1; } /** * 交換陣列中兩個元素的位置 */ public static <AnyType extends Comparable<? super AnyType>> void swap(AnyType[] arr, int i, int j) { if (arr == null || arr.length <= 1 || i == j) { return; } AnyType tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } }