十大排序算法之希尔排序

希尔排序

希尔(音同 Shell)排序,也叫缩小增量排序,它通过将原始列表分解多个子列表来改进插入排序。虽然它叫希尔排序,但和命令解析器 Shell 不是一回事,只是因为该算法是由 D.L.shell 提出的而已。

1. 算法思想

希尔排序法摒弃了直接插入排序逐一比较的方式,而是对指定距离(增量d)的元素进行比较,并不断把增量缩小至1,直到排序完成。

注意:对于增量取值的规律,可以是奇数、偶数或者质数等,并且不断将增量除以 2直至其值为1。

2. 算法步骤

(1)选取增量 d = n 2 d=\frac{n}{2} d=2n
(2)将待排序数组分为d个子序列,然后分别进行直接插入排序。
(3) 将構康取半,即 d = d 2 = n 2 2 d=\frac{d}{2}=\frac{\frac{n}{2}}{2} d=2d=22n
(4)重复步骤(2)和(3),直到增量d等于1。
(5)对整个待排序数组进行直接插入排序,然后完成排序。

3. 算法分析

同样,还是用例子和图来帮助大家理解这个算法。假设我们要对数组[3,13,1, 8, 2,21,1,5]进行排序,由于有两个1,所以将第二个1标记为“1*”。
首先,待排序数组长度n=8,选取增量d= n 2 \frac{n}{2} 2n=4,则第1遍排序过程如下图所示。
在这里插入图片描述
第2遍排序时增量 d = d 2 = 2 d=\frac{d}{2}=2 d=2d=2,排序过程如下图所示。
在这里插入图片描述
第3 遍排序时增量 d = d 2 = 1 d=\frac{d}{2}=1 d=2d=1,排序过程如下图所示。
在这里插入图片描述
这样看起来似乎希尔排序并不比直接插入排序快。其实不是这样的,让我们来分析一下。开始时,希尔排序的增量 d 较大——分组较多,每组记录较少,因此直接插入排序的速度较快,后来增量d缩小——分组减少,每组记录增多,但各组内的记录均已为正序,因此排序速度还是比正常情况下的直接插入要快。看出来了吗?其实希尔排序相较于直接插入排序,就是优化了待排序数组的初始顺序,使其达到或接近于直接插入排序的最好情况。
由于增量的取值不同,增量的个数也不同,所以希尔排序算法的时间复杂度分析十分复杂。如果增量取值合理的话,则时间复杂度约为 O ( n 1.3 ) O(n^{1.3}) O(n1.3)。当然,若运气不好,则最坏情况的时间复杂度依然为 O ( n 2 ) O(n^2) O(n2),并且希尔排序为不稳定排序。

4. 算法代码

算法代码如下:
Python

# 希尓排序
def shell_sort (array) :
    #设定初始增量d = n/2
    d = len(array)//2 #“//” 表示整数除法
    #当增量大于0时执行,如果小于0,则退出循环
    while d >0:
        #i的取值范围为d到n
        for i in range(d,len(array)):
            # 类似于直接插入排序,比较当前值与之前指定增量的值
            while i >= d and array[i-d]> array[i]:
                # 符合条件,则交换位置
                array[i],array[i-d]=array[i-d],array[i]
                # 取前一个指定增量的值,继续下一个判断
                i-=d
        # 将增量取半,回到 while 外循环
        d=d//2
    return array
# 调用 shell_sort 函数
print(shell_sort([34,21,13,2,5,1,55,3,1,8]))

java

 			int[] array ={
   34,21,13,2,5,1,55,3,1,8};
            int n = array.length/2;
            while (n>0){
   
                for (int i=n;i<array.length;i++){
   
                    while (i>=n && array[i-n]>array[i]){
   
                        int t= array[i];
                        array[i]=array[i-n];
                        array[i-n] = t;
                        i -= n;
                    }
                }
                n=n/2;
            }
            System.out.println(Arrays.toString(array));

5. 输出结果

在这里插入图片描述

6. 算法过程分解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

相关推荐

  1. 经典排序算法排序。

    2024-02-01 23:02:04       13 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-01 23:02:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-01 23:02:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-01 23:02:04       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-01 23:02:04       20 阅读

热门阅读

  1. ubuntu源码编译安装memcached和php-memcache 扩展

    2024-02-01 23:02:04       27 阅读
  2. 如何docker部署springboot项目

    2024-02-01 23:02:04       28 阅读
  3. 如何在python程序内连续运行多个代码

    2024-02-01 23:02:04       35 阅读
  4. 达梦数据库死锁排查与解决

    2024-02-01 23:02:04       36 阅读
  5. 【AI_Design】Midjourney技巧进阶

    2024-02-01 23:02:04       34 阅读
  6. 2023年常用网络安全政策标准整合

    2024-02-01 23:02:04       33 阅读
  7. 自定义View

    2024-02-01 23:02:04       32 阅读
  8. jsonwebtoken使用HS256生成token失败

    2024-02-01 23:02:04       34 阅读
  9. C++从零开始的打怪升级之路(day28)

    2024-02-01 23:02:04       29 阅读
  10. SQL语言(三)

    2024-02-01 23:02:04       31 阅读