【A-排序】python实现八大排序算法之4-希尔排序ShellSort

希尔排序ShellSort

起源:

  • 直接插入法的改进算法。希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。

希尔排序【缩小增量排序算法】基本思想:

  • 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
  • 简单插入排序很循规蹈矩,不管数组分布是怎么样的,依然一步一步的对元素进行比较,移动,插入,比如[5,4,3,2,1,0]这种倒序序列,数组末端的0要回到首位置很是费劲,比较和移动元素均需n-1次。而希尔排序在数组中采用跳跃式分组的策略,通过某个增量将数组元素划分为若干组,然后分组进行插入排序,随后逐步缩小增量,继续按组进行插入排序操作,直至增量为1。希尔排序通过这种策略使得整个数组在初始阶段达到从宏观上看基本有序,小的基本在前,大的基本在后。然后缩小增量,到增量为1时,其实多数情况下只需微调即可,不会涉及过多的数据移动。
  • 我们来看下希尔排序的基本步骤,在此我们选择增量gap=length/2,缩小增量继续以gap = gap/2的方式,这种增量选择我们可以用一个序列来表示,{n/2,(n/2)/2…1},称为增量序列。希尔排序的增量序列的选择与证明是个数学难题,我们选择的这个增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。此处我们做示例使用希尔增量.
  • 希尔排序中对于增量序列的选择十分重要,直接影响到希尔排序的性能。我们上面选择的增量序列{n/2,(n/2)/2…1}(希尔增量),其最坏时间复杂度依然为O(n2),一些经过优化的增量序列如Hibbard经过复杂证明可使得最坏时间复杂度为O(n3/2)。增量因子序列可以有各种取法,有取奇数的,也有取质数的,但需要注意:增量因子中除1 外没有公因子,且最后一个增量因子必须为1。希尔排序方法是一个不稳定的排序方法

希尔排序【缩小增量排序算法】代码实现:
- 在代码实现中,我们可以不用这么按部就班地处理完一组再调转回来处理下一组,可以在循环里面进行跨组比较。我理解的在普通的插入法外面增加一个循环,控制Gap,并逐步减少gap的值。
- 基础的插入法排序是两重循环,希尔排序是三重循环,最外面一重循环,控制增量gap,并逐步减少gap的值。二重循环从下标为gap的元素开始比较,依次逐个跨组处理。最后一重循环是对组内的元素进行插入法排序。
- 这样进行排序的有点在于每次循环,整个序列的元素都将小元素的值逐步向前移动,数值比较大的值向后移动。

'''
Creat by HuangDandan
2018-08-13
[email protected]
希尔排序是直接插入法排序的改进
希尔排序的原理:
希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;
随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

'''

#在直接插入的基础上增加增量,加一个循环,将其他两重循环中的增量1改成增量gap
#下面插入法采用的是移动法
def ShellInsertSort(Lst):
    gap = int(len(Lst)/2) #增量++++++

    times = 0
    while gap > 0:
        for i in range(gap, len(Lst)):
            x = Lst[i]
            j = i
            while j > gap and Lst[j-gap] > x:
                Lst[j] = Lst[j-gap]
                j -= gap
            Lst[j] = x
        gap = int(gap /2)

        times += 1
        print('Lst{}: {}'.format(times, Lst))

#在直接插入的基础上增加增量,加一个循环,将其他两重循环中的增量1改成增量gap
#下面插入法采用的是元素交换法
def ShellInsertSort(Lst):
    gap = int(len(Lst)/2) #增量++++++

    times = 0
    while gap > 0:
        for i in range(gap, len(Lst)):
            x = Lst[i]
            j = i
            while j > gap and Lst[j-gap] > x:
                Lst[j], Lst[j-gap] = Lst[j-gap], Lst[j]
                j -= gap
            #Lst[j] = x
        gap = int(gap /2)

        times += 1
        print('Lst{}: {}'.format(times, Lst))



Lst1 = [1,4,5,2,55,44,66,77,66,66,88,1]
print(Lst1)
ShellInsertSort(Lst1)
print(Lst1)
print('------------------------------------')

参考博客:https://www.cnblogs.com/chengxiao/p/6104371.html

猜你喜欢

转载自blog.csdn.net/u010591976/article/details/81809732