排序算法-希尔排序(Shell Sort)

灰太狼 2023-07-02 04:25 71阅读 0赞

文章目录

      • 希尔排序法介绍
      • 希尔排序法算法
      • 时间复杂度
      • 稳定性
      • 其他排序法的比较

希尔排序法介绍

希尔排序法(Shell Sort)是D.L.Shell于1959年提出的一种排序算法,是直接插入排序法的更高效的改进版。在这之前的排序算法如冒泡排序、简单选择排序、直接插入排序等算法的的时间复杂度都为 O ( n 2 ) O(n^{2}) O(n2),而希尔排序突破了这一时间复杂度。
【原理】
直接插入排序算法比冒泡排序和简单选择排序性能都要高,尤其在序列基本有序并且记录数相对较少的情况,只需要简单的几个插入动作就能完成排序。

希尔排序的思路就是在插入排序算法的基础上,创造插入排序算法的有利条件,将序列按照某个增量分成多个子序列进行插入排序,使整个序列变为基本有序,并且由于按照增量分了子序列,所以每个子序列的记录数变少了,增量和子序列长度成反比,增量从小于n的某个值每次递减,子序列随增量变小而变长。直到增量变为1,使其所有记录为一个整体序列然后进行一次插入排序为止。

什么才叫基本有序呢?比如{2,1,4,3,5,6,8,7,9}可以说是基本有序,小的数字基本在序列的前部,不大不小的在中部,大的数字在后部。 {8,7,6,3,9,2,4,5,1}这样的序列就不是基本有序,因为1在序列的最后,9在中间,8在第一位,所以谈不上是基本有序的。

【例子】
下面看个对关键字序列{8,7,1,9,3,6,4,5,2}进行希尔排序的步骤。
在这里插入图片描述

希尔排序法算法

  1. public static void shellSort(Integer[] arr) {
  2. int increment = arr.length;
  3. do {
  4. increment = increment / 3 + 1;
  5. for (int i = increment; i < arr.length; i++) {
  6. if (arr[i-increment] > arr[i]){
  7. int minIdx = i;
  8. int compIdx = minIdx-increment; //需往右边移动的关键字下标
  9. int minValue = arr[minIdx];
  10. while (compIdx >= 0 && arr[compIdx] > minValue) { //比较大小
  11. arr[minIdx] = arr[compIdx]; //关键字右移
  12. minIdx = compIdx;
  13. compIdx = compIdx - increment;
  14. }
  15. arr[minIdx] = minValue; //插入关键字
  16. }
  17. }
  18. } while (increment > 1);
  19. }

时间复杂度

希尔排序的时间复杂度依赖增量序列,增量的取值至今还是个难题,大量研究表明,当增量序列为delta[k]= 2 t − k + 1 2^{t-k+1} 2t−k+1-1(0 ⩽ \leqslant ⩽k ⩽ \leqslant ⩽t ⩽ ⌊ l o g 2 ( n + 1 ) ⌋ \leqslant \left \lfloor log2(n+1) \right \rfloor ⩽⌊log2(n+1)⌋) 时,可以获得不错的效率,其时间复杂度为 O ( n 3 / 2 ) O(n^{3/2}) O(n3/2),要好于直接插入排序的 O ( n 2 ) O(n^{2}) O(n2)。

稳定性

由于按照增量跳跃式分成了子序列插入排序,所以相同值位置可能会被替换,所以希尔排序是不稳定的。

其他排序法的比较

以下分别使用简单选择排序法、直接插入排序法和希尔排序法对10万随机关键字的排序耗时,从结果可以看出直接插入排序的执行时间比简单选择排序法快,而希尔排序法比直接插入排序法快了非常多只用了38ms。

  1. 简单选择排序执行时间:8077ms
  2. 直接插入排序执行时间:4408ms
  3. 希尔排序执行时间:38ms

发表评论

表情:
评论列表 (有 0 条评论,71人围观)

还没有评论,来说两句吧...

相关阅读

    相关 排序算法排序

    一、前言     希尔(Shell)排序又称为缩小增量排序,它是一种插入排序。它是直接插入排序算法的一种威力加强版。     希尔排序,也称递减增量排序算法,以其设计