十大排序算法之希尔排序

希尔排序

希尔(音同 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. 算法过程分解

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

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忆梦九洲

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值