• python排序算法(六)、希尔排序


    插入排序

    假如有一个列表[5, 7, 4, 6, 3, 1, 2, 9, 8],将此列表当作桌子上的牌,最开始我们手里有一张牌5, 此时我们依次从剩余的牌[7, 4, 6, 3, 1, 2, 9, 8]中摸出牌来与手中的牌进行对比,手里的牌只要大于摸到的牌则往右走,最后将摸到的牌插入到合适的位置

    插入排序代码:

    1. def insert_sort(li):
    2. for i in range(1, len(li)): # i 代表我即将摸到牌的下标[7, 4, 6, 3, 1, 2, 9, 8]
    3. tmp = li[i] # 代表我当前摸到的牌
    4. k = i - 1 # 表示我现在手里的牌的数量[0 - k]
    5. while k >= 0 and li[k] > tmp: # 循环从右遍历手里的牌,如果当前手里的牌大于摸到的牌,则将手里的牌放到摸到的牌的位置
    6. li[k + 1] = li[k]
    7. k -= 1
    8. li[k + 1] = tmp # 最后对比完手里的牌将摸到的牌放到合适的位置

    希尔排序(shell Sort)是一种分组插入排序算法。

    希尔排序的具体思路步骤:(n等于列表的长度)

    • 首先取一个整数d1 = n // 2 ,将元素分为d1个组,每组相邻元素之间的距离为d1,在各组内进行插入排序
    • 取第二个整数d2 = d1 // 2 ,重复上述分组排序,则到di =1时,即所有元素在同一组内进行插入排序即可完成排序
    • 希尔排序每趟并不是使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序使得所有数据有序

    这里取列表 [5, 7, 4, 6, 3, 1, 2, 9, 8] 

    第一次分组d1 = 9 // 2 = 4 ,分成4组,依次对[5, 3, 8],  [7, 1],  [4,2], [6,9] 进行插入排序         

    574631298
    538
    71
    42
    69

    这里我们可以将 5,7,4,6看成手里的牌, 即将摸到的牌为 3,1,2,9,8。5与3比较,7与1比较,4 与 2 比较, 6 与 9 比较。元素之间间隔4个下标。 依次下一列比较

    第一次分组插入排序后:[3, 1, 2, 6, 5, 7, 4, 9, 8]

    第二次分组 d2 = d1 // 2 =2, 依次对[3,2,5,4,8]、[1,6,7,9]进行插入排序

    312657498
    32548
    1679

    第二次分组插入排序后:[ 2,1,3,6,4,7,5,9,8 ]

    第三次分组 d3 = d2 // 2 =1 则对 [ 2,1,3,6,4,7,5,9,8 ]进行插入排序,排序后[1, 2, 3, 4, 5, 6, 7, 8, 9]

    代码 

    1. def insert_sort_gap(li, gap): # gap 代表分成机组
    2. for i in range(gap, len(li)):
    3. tmp = li[i] # 第一组中即将摸的牌
    4. k = i - gap # 第一组中手里有的牌
    5. while k >= 0 and li[k] > tmp: # 摸到的牌大于手里的牌
    6. li[k + gap] = li[k] # 手里的牌交换到摸到的牌的位置
    7. k -= gap
    8. li[k + gap] = tmp # 将摸到的牌放到合适的位置
    9. print(li)
    10. def shell_sort(li):
    11. d = len(li) // 2
    12. while d >= 1:
    13. insert_sort_gap(li, d)
    14. d //= 2
    15. li = [5, 7, 4, 6, 3, 1, 2, 9, 8]
    16. shell_sort(li)
    17. print(li)

    插入排序和希尔排序对比

    1. import random
    2. import time
    3. import copy
    4. def cal_time(func):
    5. def inner(*args, **kwargs):
    6. strat = time.time()
    7. result = func(*args, **kwargs)
    8. end = time.time()
    9. print('%s执行时间:%s' % (func.__name__, end - strat))
    10. return result
    11. return inner
    12. @cal_time
    13. def insert_sort(li):
    14. for i in range(1, len(li)): # i 代表我即将摸到牌的下标[7, 4, 6, 3, 1, 2, 9, 8]
    15. tmp = li[i] # 代表我当前摸到的牌
    16. k = i - 1 # 表示我现在手里的牌的数量[0 - k]
    17. while k >= 0 and li[k] > tmp: # 循环从右遍历手里的牌,如果当前手里的牌大于摸到的牌,则将手里的牌放到摸到的牌的位置
    18. li[k + 1] = li[k]
    19. k -= 1
    20. li[k + 1] = tmp # 最后对比完手里的牌将摸到的牌放到合适的位置
    21. def insert_sort_gap(li, gap): # gap 代表分成机组
    22. for i in range(gap, len(li)):
    23. tmp = li[i] # 第一组中即将摸的牌
    24. k = i - gap # 第一组中手里有的牌
    25. while k >= 0 and li[k] > tmp: # 摸到的牌大于手里的牌
    26. li[k + gap] = li[k] # 手里的牌交换到摸到的牌的位置
    27. k -= gap
    28. li[k + gap] = tmp # 将摸到的牌放到合适的位置
    29. # print(li)
    30. @cal_time
    31. def shell_sort(li):
    32. d = len(li) // 2
    33. while d >= 1:
    34. insert_sort_gap(li, d)
    35. d //= 2
    36. #
    37. # li = [5, 7, 4, 6, 3, 1, 2, 9, 8]
    38. # shell_sort(li)
    39. # print(li)
    40. li = list(range(10000))
    41. random.shuffle(li)
    42. li1 = copy.deepcopy(li)
    43. li2 = copy.deepcopy(li)
    44. shell_sort(li1)
    45. insert_sort(li2)
    46. # 结果
    47. shell_sort执行时间:0.013513565063476562
    48. insert_sort执行时间:1.416457176208496

    插入排序的时间复杂度为:O(n²)

    希尔排序的时间复杂度为:

            最坏:O(n²)

            平均情况:O(n²) -- O(n)

  • 相关阅读:
    SpringCloud(十一)- 秒杀 抢购
    IDEA中 GIT基础操作
    Python 图片处理笔记
    【Java】main方法的深入理解
    Vue项目中如何使用Vuex进行全局管理
    Docker入门指南
    Dubbo学习
    查看系统信息和关机及重启操作
    Android 字符串工具类
    LVS+Keepalived 高可用群集
  • 原文地址:https://blog.csdn.net/adminwg/article/details/126903829