希尔排序
希尔排序是插入排序的一种。也叫做缩小增量排序。是直接插入排序的更高效的改进版。希尔排序是非稳定排序算法。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
思路:不要认为序列是一个有机的整体,而是有很多个无序的序列组成的,希尔排序就是分段分组的插入排序
1.取间隔为四,把他们分为几个无序序列
然后对每个无序序列进行插入排序
对第一个无序序列排序如下:
对第二个无序序列排序
对第三个无序序列排序
对第四个无序序列排序
第一趟排序完成之后结果如下:
2.取间隔为四二,把他们分为两个无序序列
把第一个无序序列按照插入算法排序后结果如下:
把第二个无序序列按照插入算法排序后结果如下:
第二趟排序完成之后结果如下:
3.取间隔为一,即他们就是一个无序的序列
如下图:
然后对这个无序序列进行插入算法排序
写算法的时候i的值为如下图
i从一个序列的中间位置开始取值,然后每次加一,加一的同时在自己这一行进行插入排序,
整体考虑的话如下:
第一次i=gap(没有拿20来比较大小):
第二次i=gap+1:
第三次i=gap+2:
比较完成之后进行交换
第四次:
第五次:
i=gap+4即为最后一个元素,然后在这里进行插入排序
希尔排序算法的内层是插入排序算法。
#希尔排序每个无序部分还是按照插入排序写的
def shell_sort(alist):
"""希尔排序"""
n=len(alist) #n=9
gap=n//2 #间隔取队列长度的一半,下一次再取, gap=4
#这个while循环控制的是gap变化到1的过程中执行的次数
while gap>=1: #步长需要取到1,因为2个子序列有序不意味着两个子序列合到一起之后也是有序的
#希尔算法,与普通插入算法的区别就是gap步长。
for j in range(gap,n): #外层循环控制的是所有子序列的所有元素
i=j
#内层循环控制的是子序列执行的特定算法的比较和交换
while i >= gap: #while i>0: 他比较到最前端的一个元素时停止比较
if alist[i]<alist[i-gap]:
alist[i],alist[i-gap]=alist[i-gap],alist[i]
i-=gap
else:
break
gap//=2 #缩短gap步长
if __name__ == '__main__':
alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
shell_sort(alist)
print(alist)
#结果为[17, 20, 26, 31, 44, 54, 55, 77, 93]
希尔排序的不稳定性体现在如下:
把他们分成两组,两组里面有两个77
执行第二次的时候结果为:
很显然不稳定,已经破坏了排序的有序性