希尔排序详细说明及实现-python

算法思想:

        将序列以某一增量分割为若干个子序列,对每个子序列进行插入排序,之后对增量进行递减,重复上述步骤,直到增量为1时,此时进行的插入排序就是基本的插入排序,完成后序列有序。


这里的增量的取值不固定,每一种取值方法造成的时间复杂度不一样。

我们一般以序列长度的一半为增量起始值。即 n//2作为增量起始值。

 

 

         可以发现,每次插入排序,会把每次增量分割得到的子序列进行排序。可以快速使序列向有序方向发展。最后一次增量为1,就是执行一次常规的插入排序,遍历整个序列完成排序。

        因为当增量为1时,序列已基本有序,交换次数大大减小,规避了从序列末尾一直交换到序列首部等耗时操作。因此希尔排序也可以看做插入排序的一种更高效的改进版本。

 实现代码:

将插入排序理解为打扑克牌时揭牌,插入到手中的牌,插入时从右边较大的牌开始比较,遇到比左边大的就插在它右边,这样过程会很简单。

# 将插入排序进行修改
def insert_sort_gap(li, gap):  # gap 为间隔
    for i in range(gap, len(li)):  # i 表示摸到牌的下标
        tmp = li[i]  # 将数暂存到tmp
        j = i - gap  # j指得是手里的牌的下标,起始为最右边的下标
        while j >= 0 and li[j] > tmp:  # 让tmp与前面的牌比较大小
            li[j + gap] = li[j]  # tmp小于前面的牌就与它交换位置
            j -= gap
        li[j + gap] = tmp  # 当tmp大于了前面的牌时或前面没有牌了,就把tmp插入到其后面


def ShellSort(li):
    d = len(li) // 2  # 增量,我们定为序列长度的一半
    while d >= 1:  # 当增量为1时进行排序就是执行的基本的插入排序,完成后序列有序
        insert_sort_gap(li, d)  # 对不同增量进行插入排序,使序列逐渐有序
        d //= 2  # 每次增量插入排序完成后,增量进行递减,直到为1最后一次进行插入排序。


li = [5, 2, 8, 9, 6, 4, 7, 1, 3]
ShellSort(li)
print(li)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]



# -----------------------------下面是整合到一起的代码------------------------------

def ShellSort(li):
    d = len(li) // 2  # 增量,我们定为序列长度的一半
    while d >= 1:  # 当增量为1时进行排序就是执行的基本的插入排序,完成后序列有序
        for i in range(d, len(li)):  # i 表示摸到牌的下标,数的下标
            tmp = li[i]  # 将数暂存到tmp
            j = i - d  # j指得是手里的牌的下标,起始为最右边的下标
            while j >= 0 and li[j] > tmp:  # 让tmp与前面的牌比较大小
                li[j + d] = li[j]  # tmp小于前面的牌就与它交换位置
                j -= d
            li[j + d] = tmp  # 当tmp大于了前面的牌时或前面没有牌了,就把tmp插入到其后面
        d //= 2  # 每次增量插入排序完成后,增量进行递减,直到为1最后一次进行插入排序。

li = [5, 2, 8, 9, 6, 4, 7, 1, 3]
ShellSort(li)
print(li)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

排序过程如图所示:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

onlywishes

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

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

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

打赏作者

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

抵扣说明:

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

余额充值