博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python经典算法(小白入门系列)------希尔排序
阅读量:2394 次
发布时间:2019-05-10

本文共 3681 字,大约阅读时间需要 12 分钟。

文章目录

希尔排序是插入排序的一个优化,如果对插入排序还有点模糊的同学,可以移步另一篇博文里面:

1.希尔排序相比插入排序,哪些地方可以优化?

在这里插入图片描述

  • 插入排序的做法是,最外层循环控制开始从第几个元素开始笔记,例如i
  • 内部循环是,从上面的i元素开始,往前面比较。如果list[i] < list[i-1]就调换顺序
  • 在最坏的情况,每次比较两个元素,每次都需要调换顺序,那肯定效率就会慢很多
  • 如果我们选择的列表,是相对有序一些的。即比较的次数虽然没变,但是需要调换位置的次数如果能降低很多,也可以节省效率。
  • 核心:计算机的计算是非常快的,但是调换元素的位置,涉及到内存的开销,相对会慢一些。所以我们尽可能降低调换顺序,多选用计算的方式。

2.希尔排序—分步图解优化的方案

让数据列表相对更有序一些,可以用间隔的方式:

  • 每次使用间隔减半的方式分组,然后再对每组进行比较,就可以达到相对有序的程度
  • 即gap = n // 2

原始的数据如下:

在这里插入图片描述

第一次分组,分了四组时候的情况:

在这里插入图片描述

  • 每个虚线方框算一组,共计四组
  • 从索引为4的元素开始,每次与前面那个相差gap的元素比较,即索引4---->索引0比较,索引5----->索引1比较
  • 如果前面的元素大,则每组中的两个元素调换位置

比较完之后,发现第2组和第4组需要调换位置

在这里插入图片描述

最终看到的数组,虽然整体没什么改观,但还可以继续往下分组排序:

在这里插入图片描述

上次gap = n// 2 , gap = 4,分了4组,继续使用gap = gap//2 分组,得到gap = 2,分2组,分组情况如下:

  • 第1次循环,从第2个(此时的gap数)索引开始,与前面间隔gap=2的数比较,2-2 = 0,所以前面能比较的只有索引为0的数
  • 同理,第2次循环是,索引3与索引1比较
  • 第3次循环的时候,索引4,与前面索引2比较,然后索引2与索引0再比较。两两比较,依次往前推进
  • 第4次同理直到i+gap数,与i数比较完毕,次数i为0。(这个过程其实是插入排序)

在这里插入图片描述

最终比较完的结果为:

在这里插入图片描述

通过如上发现,看着还挺有序的,已经有效果了,此时,我们再进行插入排序,效率就杠杠的了!

3.分拆希尔排序------一次分组的排序

my_list = [5, 9, 1, 11, 6, 7, 2, 4]gap = 4n = len(my_list)for i in range(gap, n):    print("----------%d------------" % i)    while my_list[i - gap] > my_list[i] and i >= gap:			# 注意,此处为i最小值为gap        my_list[i - gap], my_list[i] = my_list[i], my_list[i - gap]        print("-->", my_list, "-->", i)        i = i - gap												# 每次比较的时候,向前移动gap位置    print( my_list)
----------4------------					# 这里的值,就是我们说的最外层的循环,每次从哪个索引开始,一个一个往前面比较[5, 9, 1, 11, 6, 7, 2, 4]----------5--------------> [5, 7, 1, 11, 6, 9, 2, 4] --> 5		# 带-->箭头的,说明有元素相互替换了[5, 7, 1, 11, 6, 9, 2, 4]----------6------------[5, 7, 1, 11, 6, 9, 2, 4]----------7--------------> [5, 7, 1, 4, 6, 9, 2, 11] --> 7[5, 7, 1, 4, 6, 9, 2, 11]

以上代码,如果对比着插入排序的分拆代码看,会简单很多的,插入排序一定要先搞清楚再研究这个希尔排序!!!

4.分拆希尔排序—完整代码

my_list = [5, 9, 1, 11, 6, 7, 2, 4]n = len(my_list)gap = n // 2while gap >= 1:    print("=====gap is :%d=========" % gap)    for i in range(gap, n):        print("----------%d------------" % i)        while my_list[i - gap] > my_list[i] and i >= gap:            my_list[i - gap], my_list[i] = my_list[i], my_list[i - gap]            print("-->", my_list, "-->", i)            i = i - gap        print(my_list)    gap = gap // 2
=====gap is :4=========----------4------------[5, 9, 1, 11, 6, 7, 2, 4]----------5--------------> [5, 7, 1, 11, 6, 9, 2, 4] --> 5[5, 7, 1, 11, 6, 9, 2, 4]----------6------------[5, 7, 1, 11, 6, 9, 2, 4]----------7--------------> [5, 7, 1, 4, 6, 9, 2, 11] --> 7[5, 7, 1, 4, 6, 9, 2, 11]=====gap is :2=========----------2--------------> [1, 7, 5, 4, 6, 9, 2, 11] --> 2[1, 7, 5, 4, 6, 9, 2, 11]----------3--------------> [1, 4, 5, 7, 6, 9, 2, 11] --> 3[1, 4, 5, 7, 6, 9, 2, 11]----------4------------[1, 4, 5, 7, 6, 9, 2, 11]----------5------------[1, 4, 5, 7, 6, 9, 2, 11]----------6--------------> [1, 4, 5, 7, 2, 9, 6, 11] --> 6--> [1, 4, 2, 7, 5, 9, 6, 11] --> 4[1, 4, 2, 7, 5, 9, 6, 11]----------7------------[1, 4, 2, 7, 5, 9, 6, 11]=====gap is :1=========----------1------------[1, 4, 2, 7, 5, 9, 6, 11]----------2--------------> [1, 2, 4, 7, 5, 9, 6, 11] --> 2[1, 2, 4, 7, 5, 9, 6, 11]----------3------------[1, 2, 4, 7, 5, 9, 6, 11]----------4--------------> [1, 2, 4, 5, 7, 9, 6, 11] --> 4[1, 2, 4, 5, 7, 9, 6, 11]----------5------------[1, 2, 4, 5, 7, 9, 6, 11]----------6--------------> [1, 2, 4, 5, 7, 6, 9, 11] --> 6--> [1, 2, 4, 5, 6, 7, 9, 11] --> 5[1, 2, 4, 5, 6, 7, 9, 11]----------7------------[1, 2, 4, 5, 6, 7, 9, 11]
# 如下代码,可能会更容易理解一些,和上面其实本质一样的my_list = [5, 9, 1, 11, 6, 7, 2, 4]n = len(my_list)gap = n // 2while gap >= 1:    for i in range(gap, n):        while i >= gap:            if my_list[i - gap] > my_list[i]:                my_list[i - gap], my_list[i] = my_list[i], my_list[i - gap]            i = i - gap    gap = gap // 2

以上内容有哪里不太容易看懂的,可以留言说明,我争取不断优化!

转载地址:http://iteab.baihongyu.com/

你可能感兴趣的文章
MMS彩信是怎么炼成地(一) 编辑
查看>>
MMS是怎样炼成的(二)封装
查看>>
SMIL 参考手册
查看>>
分析pptpd程序中关于执行pptpd和pppd程序的部分源代码
查看>>
RFC 1180 - TCP/IP tutorial 学习笔记
查看>>
HOWTO: Unpack, Edit, and Re-Pack Boot Images
查看>>
ramfs, rootfs &amp; initramfs
查看>>
Tom's attempts to get GPRS working over bluetooth with his laptop
查看>>
Connecting to GPRS over Bluetooth on Linux
查看>>
Linux网络资源
查看>>
Android对Kernel的改动汇总
查看>>
WGET 通过代理下载
查看>>
JITTER BUFFER
查看>>
IP协议报头学习笔记
查看>>
关于SIGPIPE导致的程序退出
查看>>
基于MTD的NAND驱动开发
查看>>
linux mtd源码分析(好东西)
查看>>
关于SIGBUS的总结
查看>>
JSP--9大隐式对象
查看>>
Servelt中主要对象的使用
查看>>