最近在研究尋找最大的K個數,裏面提到了利用最小堆,因此就順便了解了一下。java
package com.xylx.utils.selectK; import com.xylx.utils.GsonUtils; /** * Created by zongjh on 17-5-10. */ public class MinHeap { public static void main(String[] args) { int[] arr = {2,6,3,9,4,8}; buildMinHeap(arr); System.out.println(GsonUtils.getJsonFromObject(arr)); change(5, arr); System.out.println(GsonUtils.getJsonFromObject(arr)); change(4, arr); System.out.println(GsonUtils.getJsonFromObject(arr)); } /** * 都建構建最小堆 * @param arr */ public static void buildMinHeap(int[] arr) { for (int i=0; i<arr.length; i++) { handleMinHeap(arr, arr.length, i); //從前向後構建最小堆 } } /** * 檢查value是否比arr[0]大,若是大於,則對堆進行重構 * @param value * @param arr */ public static void change(int value, int[] arr) { if (value > arr[0]) { arr[0] = value; handleMinHeap(arr, arr.length, 0); } } /** * 最小堆排序 * @param arr */ public static void minHeapSort(int[] arr) { for (int i=arr.length-1; i>0; i--) { int temp = arr[0]; arr[0] = arr[i]; arr[i] = temp; handleMinHeap(arr, i, 0); } } /** * 節點轉換 * @param arr * @param heapSize * @param current */ public static void handleMinHeap(int[] arr, int heapSize, int current) { int leftChildIndex = getLeftChiledIndex(current); int rightChildIndex = getRightChildIndex(current); int minIndex = current; //找到三個節點中最小的那個 if (leftChildIndex<heapSize && arr[current] > arr[leftChildIndex]) { minIndex = leftChildIndex; } if (rightChildIndex<heapSize && arr[minIndex] > arr[rightChildIndex]) { minIndex = rightChildIndex; } if (minIndex != current) { int tmp = arr[current]; //將最小的值轉移到父節點位置,這樣可能會破壞原先子節點的結果,因此須要遞歸 arr[current] = arr[minIndex]; arr[minIndex] = tmp; handleMinHeap(arr, heapSize, minIndex); } } /** * 獲取左孩子節點位置 * @param current * @return */ public static int getLeftChiledIndex(int current) { return (current<<1) + 1; } /** * 獲取右孩子節點位置 * @param current * @return */ public static int getRightChildIndex(int current) { return (current<<1) + 2; } /** * 獲取父節點位置 * @param current * @return */ public static int getParentIndex(int current) { return (current-1)>>1; } }
下面是一個輔助類:主要用於數據生成和打印。數組
package com.xylx.utils.selectK; import java.util.Arrays; import java.util.Random; /** * Created by zongjh on 17-5-6. */ public class Constans { private static int JI_ZHUN = 100; public static int K = 10; /** * 生成長度爲length的int類型數組 * @param length * @return * @throws Exception */ public static int[] getLengthArr(int length) { if (length<1) { length = 100; } int[] arr = new int[length]; int[] yzArr = new int[length]; Random random = new Random(); for (int i=0; i<length; i++) { arr[i] = random.nextInt(JI_ZHUN); yzArr[i] = arr[i]; } System.out.println("參加排序前,使用Java自帶函數排序,結果爲:"); System.out.println("=========================================="); Arrays.sort(yzArr); for (int i=0; i<yzArr.length; i++) { System.out.print(yzArr[i]+" "); } System.out.println("\n=========================================="); System.out.println(); return arr; } public static void printArr(int[] arr) { System.out.println("數組輸出:"); for (int i=0; i<arr.length; i++) { System.out.print(arr[i]+" "); } System.out.println(); } /** * 校驗排序是否正確 * @param arr * @return */ public static boolean isOk(int[] arr) { for (int i=0; i<arr.length-1; i++) { if (arr[i+1] < arr[i]) { return false; } } return true; } public static void selectK(int[] arr) { System.out.println("最大的K個數:"); for (int i=arr.length-K; i<arr.length; i++) { System.out.print(arr[i]+" "); } System.out.println(); } }
關於一個節點其父節點和字節的位置能夠參考如下說法:dom
若是下標從0開始:函數
父節點=(i-1)/2學習
左子節點:2*i + 1ui
右子節點:2*i + 2排序
若是下標從1開始遞歸
父節點:i/2get
左子節點:2*iio
右子節點: 2*i + 1
喜歡聊技術或者聊觀點,能夠加入公號:【花生讀書匯】
一塊兒:勵志,成長,學習,分享。