最近在研究寻找最大的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
喜欢聊技术或者聊观点,能够加入公号:【花生读书汇】
一块儿:励志,成长,学习,分享。