数据结构复习总结之希尔排序(三)

先来看一下希尔排序:

原理概述

希尔排序其实是插入排序的改进版本,性能会有所提升,该算法设置一个gap步长(后续会变化),选取原序列的隔步长的元素组成一个子表,对该子表使用插入排序,其实很明显的就是每设置一个步长该原序列就会被分成gap个子表,对所有子表都分别进行插入排序,也就是在各自的表顺序内进行插入排序,但是操作的元素仍是原表中对应的索引(而不是新的子表中的索引,所以子表中每两个元素之间的间隔为gap)。接下来再让gap减半,这样子表的数目减少,每个子表中的元素变多,然后对这些新的子表仍然进行插入排序,接下来再让gap减半,再对生成的新的子表插入排序,,,以此类推,知道最后gap=1也就是会有一个原序列作为子表(其实只是顺序不一样了,长度还是原序列的长度,因为步长为1嘛)

代码实现

我发现我的智商真的有问题,,,,,想了好久,,,,我,,,

# -*- coding: utf-8 -*-
"""
Created on Sat May 26 13:45:51 2018

@author: Administrator
"""

#**********************************希尔排序**********************************
def Shell_sort(L):
    n=len(L)
    gap=n//2
    while gap>=1:
        for i in range(gap):  #0,1,2,3
            member=int((n-1-i)/gap)+1  #每一组有多少元素 #3,
            for j in range(1,member):
                for k in range(j,0,-1):
                    if L[i+k*gap]<L[i+k*gap-gap]:
                        L[i+k*gap],L[i+k*gap-gap]=L[i+k*gap-gap],L[i+k*gap]
        print(L)
        gap=int(gap/2)

    print(L)        

if __name__=="__main__":
    Shell_sort([2,6,1,3,0,4,8,5])
结果展示
[0, 4, 1, 3, 2, 6, 8, 5]
[0, 3, 1, 4, 2, 5, 8, 6]
[0, 1, 2, 3, 4, 5, 6, 8]
[0, 1, 2, 3, 4, 5, 6, 8]

这里我把初始步长设为4,然后每次减半,把每次结果都打印了(4,2,1对应三个排序结果)最后一个是最终排好的我又打印了一次。

虽然写出来了,可是并不是秒做,,不开心。

嗯,刚才看了一下老师的解决思路,发现又被秒了好嘛,哼
先说一下具体的思路:

解题思路

首先就是把原始的序列分成gap份 也就相当于有gap个子序列,我们需要对当前gap下划分的这gap个子序列进行初步排序,也就是此次gap结束后每一个子序列都必须排好序,然后对于下一次gap划分仍然采取上述步骤进行插入排序
先把数据分为子序列的第一个元素和子序列需要比较(插入)的元素,然后对于后边一部分元素,我们不是把第一个子序列都比较好之后再开始第二个子序列的排序,而是把子序列待排序部分的第一个进行插入排序,因为他们都是gap,gap+1,gap+2,,,n-1 这些值,他们前面的元素都是各自索引-gap即可(说的好啰嗦,直接看代码比较好)

嗯,看懂老师的思路之后自己又写了一个,思路是一样的,如下:
嗯,发现我还是不太喜欢用while,略略略~

#*************************希尔排序(by_teacher)***************************
def Shell_sort2(L):
    n=len(L)
    gap=n//2 #设置gap步长
    print("希尔排序之前:",L)
    while gap>=1:

        for i in range(gap,n):#插入排序的遍历次数(对于此gap下)
            for j in range(i,0,-gap):
                if L[j]<L[j-gap]:
                    L[j],L[j-gap]=L[j-gap],L[j]
        gap//=2
    print("希尔排序之后:",L)
结果展示
希尔排序之前: [2, 6, 1, 3, 0, 4, 8, 5]
希尔排序之后: [0, 1, 2, 3, 4, 5, 6, 8]
时间复杂度

关于希尔排序,其实本质上就是插入排序的升级版,所以当你取gap=1时它就是插入排序,所以最坏的时间复杂度就是O(n^2)
最好的时间复杂度取决于gap的选择

稳定性

虽然插入排序是稳定的,但是希尔排序却不是,因为希尔排序实现对子序列进行排序,也就是对于每一个gap,都是把各个子序列排好序,比如
12,94,77,77,89,1
取gap=2,那么两个子序列:
12,77(前面的77),89
94,77(后边的77),1
对于第二个子序列,插入排序之后,77(后面的)就会跑到第一个位置
而第一个子序列的77(前面的)仍然在原来的位置
这样一来当gap=1插入排序时原序列后面的77就会比原序列前面的77位于更前的位置,所以该算法不稳定

排序算法比较

最后三个(堆排序,归并排序,快速排序)接下来就会有啦
排序算法比较

猜你喜欢

转载自blog.csdn.net/jiaowosiye/article/details/80463025