最小化堆堆排
堆的难点在于:
-
取出最小值时,需要向下过滤,找出次小值顶替最小值位置
-
插入时,需要向上回溯找到插入值的位置
public class Heap { private int[] nums; private int base = 0;//堆容量基数,扩容时使用 //capacity 初始化堆大小 public Heap (int capacity){//创建一个空堆 nums = new int[capacity+1];//使用nums[0]来存放当前堆中元素个数 base = capacity; } //堆扩容 private void dilatation () { int[] newHeap = new int[2*base + 1]; for (int i=0; i < nums.length; i++){ newHeap[i] = nums[i]; } nums = newHeap; } //向上回溯(核心) private void adjustUp (int[] nums, int poi){ int lf = nums[2*poi];//左子 if (lf > nums[poi]) { nums[2*poi] = nums[poi]; nums[poi] = lf; } if (2*poi+1 <= nums[0]) {//存在右子(右子可能不存在) int rt = nums[2 * poi + 1];//右子 if (rt > nums[poi]) { nums[2*poi+1] = nums[poi]; nums[poi] = rt; } } } //一轮向上过滤 private void up (int[] nums){ if (nums[0] <= 1) return; int poi = nums[0]/2; while (poi > 0) { adjustUp(nums, poi); poi--; } } //堆排 private void sortHeap (int[] arr) { int len = arr.length; if (len == 0) return; int[] nums = new int[len+1]; for (int i=1; i < len+1; i++) nums[i] = arr[i-1]; nums[0] = len; int count = nums[0]; while (nums[0]-1 > 0){ up(nums); //每轮排序完都应将最堆顶(最大值)与堆尾交换 int t = nums[0]; int tmp = nums[t]; nums[t] = nums[1]; nums[1] = tmp; nums[0]--; } nums[0] = count; for (int i=0; i < len; i++) arr[i] = nums[i+1]; } //堆排 private void sortHeap () { int count = nums[0]; while (nums[0]-1 > 0){ up(nums); //每轮排序完都应将最堆顶(最大值)与堆尾交换 int t = nums[0]; int tmp = nums[t]; nums[t] = nums[1]; nums[1] = tmp; nums[0]--; } nums[0] = count; } //入堆(可能需要扩容): 堆的构建是通过入堆时产生的,所以没有构造函数 public void put (int num) { int poi = nums[0] + 1; if (poi == nums.length)//数组已满 dilatation();//扩容 nums[poi] = num; nums[0]++; sortHeap(); } //遍历 public void travelHeap () { int len = nums[0]; if (len == 0) return; for (int i=1; i <= len; i++){ System.out.print(nums[i] + " "); } System.out.println(); } //最小元素出堆 public int pop (){ if (nums[0] == 0) return -1;//堆空 int target = nums[1]; //重新调整 (此处如果用指针可以将时间复杂度变为o(1)) if (nums[0] > 1) { //整体前移一位即可 for (int i=2; i <= nums[0]; i++) nums[i-1] = nums[i]; } nums[0]--; return target; } public static void main (String[] args) { int[] arr = {1, 8, 1, 3, 8, 3, 8, 4, 5, 1}; Heap heap1 = new Heap(10); heap1.sortHeap(arr); for (int i : arr) System.out.print(i + " "); System.out.println(); Heap heap2 = new Heap(10); heap2.put(10); heap2.put(1); heap2.put(8); heap2.put(12); heap2.travelHeap(); while (heap2.pop() != -1) heap2.travelHeap(); } }