• 【排序算法】03堆排序


    接上文: 【排序算法】02归并排序

    堆排序是对选择排序的改进。
    
    --- 适用于:
        基本有序(正序或反序)的情况。
    
    --- 堆的定义:
    对于数列{r[1], r[2], ... , r[n]},
    小顶堆:满足r[i] <= r[2i] && r[i] <= r[2i+1],r[1]最小
    大顶堆:满足r[i] >= r[2i] && r[i] >= r[2i+1],r[1]最大
    可将堆看成一颗完全二叉树,按顺序分配的方式进行存储!
    r[1]为堆顶,r[n]为堆底。
    
      时间O(n*log(n))
       空间O(1)
      
    --- 堆排序核心:     
    在堆顶r[1]和堆底r[n]交换之后,如何将序列{r[1], ..., r[n-1]}重新调整为堆。
    
    --- 堆排序思路:
    先建一个初始大顶堆,即可选得一个最大的记录,将其与序列中最后一个记录交换,
    之后继续对序列前n-1个记录进行筛选。

    向工具类ArraySorterUtils中添加堆排序的实现,代码如下:

     1 package org.liws1.sort;
     2 
     3 import java.util.Arrays;
     4 import java.util.Comparator;
     5 
     6 /**
     7  * 数组的排序,这里统一做升序排序
     8  */
     9 public class ArraySorterUtils {
    10 
    11     private static <T> void swap(T[] datas, int i, int j) {
    12         if (i == j) return;
    13         T temp = datas[i];
    14         datas[i] = datas[j];
    15         datas[j] = temp;
    16     }
    17     
    18     public static class HeapSorter implements IArraySorter {
    19         
    20         @Override public <T extends Comparable<T>> void sort(T[] list) {
    21             // 1、建立初始大顶堆,并交换堆顶和堆底的记录
    22             buildFirstHeap(list);
    23             int len = list.length;
    24             swap(list, 0, len - 1);
    25             // 2、反复调整
    26             for (int i = len - 2; i > 0; i--) {
    27                 heapAdjust(list, 0, i);
    28                 swap(list, 0, i);
    29             }
    30         }
    31 
    32         @Override public <T> void sort(T[] list, Comparator<T> comp) {
    33             // 省略实现,跟sort(T[] list)没差
    34         }
    35         
    36         /** 
    37          * 将一个无序序列调整为大顶堆[升序用大顶堆]<br>
    38          * 是一个"自下而上"的过程。
    39          * 
    40          * 思路:
    41          * 对于有n个元素的完全二叉树,[n/2, n-1]均为叶子节点,每个叶子节点都是堆,
    42          * 所以只要从最后一个非叶子节点[n/2-1]开始,到根节点位置,依次调用heapAdjust
    43          * ,即可将一个无序序列调整为一个大顶堆。
    44          */
    45         private static <T extends Comparable<T>> void buildFirstHeap(T[] datas) {
    46             int len = datas.length;
    47             for (int i = len / 2 - 1; i >= 0; i--) {
    48                 heapAdjust(datas, i, len - 1);
    49             }
    50         }
    51         
    52         /**
    53          * 在datas[start]不是大顶堆但是其'左子树'和'右子树'都为大顶堆的情况下,
    54          * 将datas[start ... end]调整为大顶堆。
    55          * 
    56          * 注意:x的子节点为2x+1和2x+2 !
    57          * @param datas 
    58          * @param start
    59          * @param end
    60          */
    61         private static <T extends Comparable<T>> void heapAdjust(T[] datas, int start, int end){
    62             int father = start;
    63             int largerKid = 2 * father + 1;
    64             while (largerKid <= end) {     // 有左子节点
    65                 // 1、确定较大子节点
    66                 if (largerKid < end) {    // 且有右子节点
    67                     if (datas[largerKid].compareTo(datas[largerKid + 1]) < 0) {
    68                         largerKid = largerKid + 1;
    69                     }
    70                 }
    71                 // 2、如果父节点记录小于较大子节点记录,则做交换;
    72                 //    否则表示已调整为大顶堆,终止循环。
    73                 if (datas[father].compareTo(datas[largerKid]) < 0) {
    74                     swap(datas, father, largerKid);
    75 
    76                     father = largerKid;
    77                     largerKid = 2 * largerKid + 1;
    78                 } else {
    79                     break;
    80                 }
    81             }
    82         }
    83 
    84     }
    85     
    86 }

    测试代码如下:

     1 package org.liws1.sort;
     2 
     3 import java.util.Arrays;
     4 import org.junit.Test;
     5 
     6 public class _Test {
     7 
     8     private Integer[] datas = { 30, 1, 29, 2, 28, 3, 27, 4, 26, 5, 25, 6, 24, 7,
     9             23, 8, 22, 9, 21, 10, 20, 19, 15, 18, 12, 17, 11, 16, 14, 13 };
    10 
    11     @Test public void testHeap(){
    12         new ArraySorterUtils.HeapSorter().sort(datas);
    13         System.out.println(Arrays.toString(datas));
    14     } // out:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
    15 }

  • 相关阅读:
    String数组转换成Integer数组
    码云远程仓库用户名和密码修改了,本地如何删除修改?
    Git操作过程(码云)
    SpringCloud应用之配置中心Nacos
    SpringCloud应用之网关GateWay
    SpringCloud应用之熔断器Hystrix
    SpringCloud应用之服务调用Feign
    装饰者设计模式
    Spring 自动装配及其注解
    Spring Bean自动装配有哪些方式?
  • 原文地址:https://www.cnblogs.com/apeway/p/10817415.html
Copyright © 2020-2023  润新知