希尔排序
基本思想:希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
希尔排序的过程:
将数组列在一个表中并对列分别进行插入排序,重复这过程,不过每次用更长的列(步长更长了,列数更少了)来进行。最后整个表就只有一列了。将数组转换至表是为了更好地理解这算法,算法本身还是使用数组进行排序。
例如,假设有这样一组数[ 13 14 94 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
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
94 65 82
45
25 23 13
27 94 33
39 25 59
94 65 82
45
排序之后变为
10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94
25 23 33
27 25 59
39 65 73
45 94 82
94
我们再将这几列数按照顺序拼接在一起,最后按照步长为1来进行排序(这一步可以看成是将一列已经具有一定规律的数进行了一遍插入排序)最后的到结果
对于希尔排序,我们所选定的步长(用gap表示)并不是固定的,对于一列数字我们可以人为的定义一个gap(通常用数组的长度来除某个值得到步长(例:数组长度为n=12 gap=n//2=6)),此时用步长gap进行第一次排序,第二次排序时我们可以用gap减去或除某个数值来得到新的gap(接上诉例子:gap=6//2=3),以此类推:当有余数时我们可以对其进行取整,直到最后我们进行了一遍gap为1的排序,然后得到了排序后的结果,希尔排序就完成了。
下面展示代码上的实现:
def shell_sort(alist):
n = len(alist)
gap = n // 2
while gap > 0:
for i in range(gap, n):
j = i
while j >= gap:
if alist[j] < alist[j - gap]:
alist[j], alist[j - gap] = alist[j - gap], alist[j]
j -= gap
else:
break
gap //= 2
if __name__ == "__main__":
list1 = [5, 6, 7, 4, 9, 11, 20, 1]
shell_sort(list1)
print(list1)
希尔排序的动态实现