算法学习:希尔排序(插入排序)

1、插入排序有两种,直接插入排序和希尔排序

2、希尔排序核心思想

希尔排序本质也是一种插入排序,但是是根据简单插入排序进行优化有的一种更加高效的版本,别称是缩小增量排序。
希尔排序的核心思想是将排序数组按照增量进行分组,然后对分组的元素进行直接插入排序,循环缩小分组增量,最后当增量长度为1是排序结束。

3、举例:给不同身高的人进行排序

第一步:分组,找一个间隔分组,间隔取4。间隔通常是总长度的一半,奇数偶数均可。

如图所示:0,4,8一组;1,5一组,2,6一组;3,7一组。

第二步:对于每组元素,分别进行排序

  第一组:0,4,8  已经排好序;

  第二组:5,1 

  第三组:6,2

  第四种:3,7

所有组拍完序后,此时:

第三步:继续设置间隔,这次的间隔是上次的一半,间隔取2

  第一组:0,2,4,6,8

  第二组:1,3,5,7

第四步:重复步骤二给每组排序:

  第一组:2,0,6,4,8

  第二组:3,7,1,5

全部排完序后:

第五步:再次设置间隔,间隔取上次的一半1

当间隔为1时,使用插入排序法,进行排序

最终结果:

方法总结:对每个分组进行插入排序

 

4、代码

对数组[83,29,30,5,99,34,12,66]使用希尔排序进行排序。

# 代码1

def shellsort(arr):
    #设置步长
    gap = len(arr)
    while gap > 0:
        #遍历分组
        for i in range(gap,len(arr)):
            #对当前分组的元素进行插入排序
            for j in range(i,gap-1,-gap):
                if arr[j] < arr[j-gap]:
                    arr[j],arr[j-gap]=arr[j-gap],arr[j]
                else:
                    break
        print(arr)
        gap //= 2# 步长减半
    return arr

arr=[83,29,30,5,99,34,12,66]
print("最终结果:",shellsort(arr))

结果:

 

#代码2:分成直接插入排序+希尔排序思想

def compare(arr,i,gap):
    #直接插入排序
    j = i-gap
    while j>=0:
        if arr[j]>arr[j+gap]:
            arr[j+gap],arr[j]=arr[j],arr[j+gap]
            j-=gap
        else:
            break


def shellSort(arr):
    gap=len(arr)//2
    while gap>=1:#步长大于0的时候,都要做以下步骤
        #1 分组
        #2 对分组的元素进行直接插入排序
        #3 缩小步长
        for i in range(gap):#对每组都要进行直接插入排序
            for j in range(i,len(arr),gap):
                compare(arr,j,gap)
        gap//=2  #一轮循环之后,才调整步长
    return arr

arr=[7,3,45,23,-1,34,88,9,4]
print(shellSort(arr))
#结果[-1, 3, 4, 7, 9, 23, 34, 45, 88]

 

5、希尔排序的时间复杂度

希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个素很少,速度很快;
当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。
所以希尔排序的时间复杂度比O(n^2)要好一些。

 

 

 

 

 

 

 

 

 
 

posted @ 2020-12-04 14:21  hqq的进阶日记  阅读(514)  评论(0)    收藏  举报