📅  最后修改于: 2023-12-03 14:51:38.649000             🧑  作者: Mango
壳排序是对插入排序的一种改进,也称为“缩小增量排序”。与插入排序不同的是,壳排序允许元素跳跃移动,以换取比插入排序更少的比较次数。
壳排序的思路是“先大后小再插入排序”,我们先将整个待排序数组按照一定的增量划分为若干个子序列,分别进行插入排序;然后逐步缩小增量,直到增量为 1 ,最后使用插入排序将整个序列排序完毕。
具体流程如下:
步骤2中,对于每个子序列,我们采用插入排序进行排序。因为每个子序列的长度相对较短,插入排序的精髓就是在少量元素时的高效率,所以采用插入排序是非常合理的。
步骤2和步骤3,由于增量序列的缘故,保证了前一个步骤得来的有序序列在下一个步骤中仍然是有序的,所以本质上是在对已经排好序的序列进行再次排序。
壳排序的代码实现分为两部分:生成增量序列和排序实现。
增量序列的生成方法并没有什么固定的规定,可以自由选择一种方法。一般来说,增量序列只要保证最后一个数是1即可。
以下是一种增量序列的生成方法:
def shell_sort_gap(len):
gap = []
i = 1
while i <= len:
gap.append(i)
i = i * 3 + 1
gap = gap[::-1]
return gap
在这个方法中,我们采用递增序列。首先设定一个数 1,然后用一个 while 循环不断将 1 乘以一个大于 1 的数,每次得到的结果加到增量序列中,直到当前的增量大于数组的长度为止。
在代码中,gap[::-1]
是将生成的增量序列翻转,就是将最后一个数 1 放到了序列的最前面。
我们使用 Python 实现壳排序的排序实现:
def shell_sort(arr):
n = len(arr)
gap = shell_sort_gap(n)
for gap_val in gap:
for i in range(gap_val, n):
temp = arr[i]
j = i - gap_val
while j >= 0 and arr[j] > temp:
arr[j + gap_val] = arr[j]
j -= gap_val
arr[j + gap_val] = temp
return arr
在这个实现中,我们先获取了增量序列,然后按照增量序列中的每个值循环进行排序。
在当前的增量之下,我们按照插入排序的思路,将每个子序列中的元素进行排序。因为增量序列是递增的,所以每次排序得到的子序列都是有序的,且已经排好序的元素均不会被打乱,所以可以保证后面的排序都是在有序序列中进行的。
壳排序的时间复杂度和增量序列的设置有关,最差情况下为 O(n^2)。但一般情况下壳排序的时间复杂度在 O(n^1.3) 左右,比插入排序的 O(n^2) 要优秀很多。
壳排序是一种内层循环使用插入排序的排序算法,所以空间复杂度为 O(1)。
壳排序在大数据随机排序的情况下,效率较高,但是也有一些性能瓶颈。因此,如果排序场景有特殊要求,需要根据实际情况选择合适的排序算法。