堆排及应用例子

最小化堆堆排
堆的难点在于:

  1. 取出最小值时,需要向下过滤,找出次小值顶替最小值位置

  2. 插入时,需要向上回溯找到插入值的位置

     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();
     
         }
     
     }
    

猜你喜欢

转载自blog.csdn.net/weixin_43247186/article/details/87364054
今日推荐