Java中的十大排序(三)希尔排序

231 阅读2分钟

「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」。

前言

上一篇章讲述了直接插入排序算法的思路,本章我们带大家来看看直接插入排序的升级版本,也就是希尔排序。

image.png

希尔排序分析

希尔排序的算法复杂度: 时间复杂度O(n^1.3) 最坏时间复杂度 O(n^2) 最好时间复杂度O(n) 空间复杂度O(1) 稳定性为不稳定

数据量大的情况下使用希尔会比直接插入排序更快,希尔就是改良了直接插入排序的大数据情况处理,大数据乱序数据直接插入会一个一个比较非常的耗时。但是在数据小的情况下,希尔排序就没有直接插入来的快了,甚至分组显得有点多余。

希尔排序通过分组的方式,直接让其前端和末端的元素进行比较,解决了插入排序这个弊端。

希尔排序实现

希尔排序主要思路:通过分组的形式一个个对比,最后形成一个相对低的在前面,相对高的在后面,注意这里说的是相对,不是绝对,分组后排序还是会有大的在前面。

已知一个无序数组
 private static int[] arr = {6, 5, 3, 2, 4};

通过数组长度/2来得出步长,根据步长先进行一遍排序。
这里的步长取整为 5/2 = 2.5 由于int 得 2

第一次分组为 (1) 6 5 3 (2) 2 4   //对比6与2并交换 插入排序
第二次分组为 (1)2 5 3 (2) 6 4    //对比5与4并交换 插入排序
第三次把分组间隔缩小到 1,然后进行直接插入排序
第四次由于间隔为1所以等于全部进行插入排序
2 3 5 6 4 //5插入到3后面,保证了前面的 2 3 为有序数列
2 3 5 6 4 //6跟前面作比较不动
2 3 4 5 6 //排序完成 4 插入到5的位置

代码实现:

@Test
public void shellSort(){
// private static int[] arr = {6, 5, 3, 2, 4};

  //步长初始值,通常为数组的一半,这里的对比方式为使用步长分组
  for (int step = arr.length / 2; step > 0; step /= 2) {
    //对每一个步长区间进行比较
    for (int i = step; i < arr.length; i++) {
      int value = arr[i];
      int j;

      //对分组中的元素进行比较
      for (j = i - step; j >= 0 && arr[j] > value; j -= step) {
        arr[j + step] = arr[j];
      }
      //交换值
      arr[j + step] = value;
    }
  }

  System.out.println(getArr(arr));

}

结论:大数据量采用希尔排序,小数据量使用直接插入或者其他排序算法,如果追求稳定性那么希尔不是你需要选择的算法。