希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,值直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分为一组,算法终止。
1、希尔排序过程
希尔排序的基本思想是:将数组在一个表中并对列进行插入排序,重复这个过程,不过每次用更长的列(步长更长了,列数更少了)来进行。最后整个表就只剩一列了。将数组转换至表是为了更好地理解这算法,算法本身还是使用数组进行排序。
例如:假设有这样一组数 [13 14 93 33 82 25 59 94 65 23 45 27 73 25 39 10] ,如果我们以步长为 5 开始进行排序,我们可以通过将这列表放在有 5 列的表中来更好地描述算法,这样他们就应该看起来是这样的(竖着的元素是步长组成的)
13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10
然后我们对每列进行排序:
10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45
将上述四行数字,依序接在一起时,得到:[10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ]
这时10已经移至正确位置了,然后再以3为步长进行排序:
10 14 73
25 23 13
27 94 33
39 25 59
45
排序之后变为:
10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94
最后以 1 步长进行排序(此时就是简单的插入排序)
2、希尔排序的分析
3、python代码实现
"""希尔排序"""
def shell_sort(alist):
n = len(alist)
# 初始步长
gap = n // 2
while gap > 0:
# 插入算法,与普通的插入算法在于步长不一样
for i in range(gap, n):
j = i
while j > 0:
if alist[j] < alist[j - gap]:
alist[j], alist[j - gap] = alist[j - gap], alist[j]
j -= gap
else:
break
gap = gap // 2
解读:初始步长为列表长度整除2后的值。当步长大于0,循环从 (步长 ~ n),将这个值 附给 j ,当 j 大于0时,进入循环,即插入排序。这样每次for循环就会将根据步长所产生的几组数据从第一组到最后一组里面的数字进行排序。这个时候,当for循环执行完毕后,就拿到了第一次以2为步长取出的列表的排序。然后再次根据步长取值,再次排序,以此类推。一直到步长为1,排序完毕。
4、时间复杂度
- 最优时间复杂度:根据步长序列的不同而不同
- 最坏时间复杂度: O(n2)
- 稳定性: 不稳定