思想
希尔排序(Shell)是直接插入排序的优化版本,实现了时间复杂度突破 O(n2) ,策略在于不断分组并在组内进行直接插入排序。那么如何分组呢?这里提出一个概念——增量序列,希尔增量 {n/2,n/4,...,1}(n为序列长度) 就是一种增量序列,增量序列里的元素称为gap。我们依次把序列分为 n/2 组, n/4 组,…,1组,即不断缩小gap,不断分组并排序,最终使序列有序。因为希尔排序涉及分组和直接插入排序,元素的前后顺序可能发生改变,所以是不稳定的排序。
示例
对序列[7,6,4,3,1,2,8,5]按升序排列。
gap | 分组 | 组内排序过程 | 排序结果 |
---|---|---|---|
4 | [7,1],[6,2],[4,8],[3,5] | [1,7],[2,6],[4,8],[3,5] | [1,2,4,3,7,6,8,5] |
2 | [1,4,7,8],[2,3,6,5] | [1,4,7,8],[2,3,5,6] | [1,2,4,3,7,5,8,6] |
1 | [1,2,4,3,7,5,8,6] | [1,2,3,4,5,6,7,8] | [1,2,3,4,5,6,7,8] |
代码
class Solution:
# @param {int[]} A an integer array
# @return nothing
def swap(self, A, i, j):
tmp = A[j]
A[j] = A[i]
A[i] = tmp
# 交换法进行插入排序
def sortIntegers(self, A):
# Write your code here
if len(A) <= 1:
return
gap = len(A) / 2
while gap > 0:
for i in range(gap, len(A)):
j = i
while j - gap >= 0 and A[j] < A[j - gap]:
# 交换法进行插入排序
self.swap(A, j, j - gap)
j -= gap
gap /= 2
# 移动法进行插入排序
def sortIntegers1(self, A):
# Write your code here
if len(A) <= 1:
return
gap = len(A) / 2
while gap > 0:
for i in range(gap, len(A)):
j = i
if A[j] < A[j - gap]:
tmp = A[j]
while j - gap >= 0 and tmp < A[j - gap]:
# 移动法进行插入排序
A[j] = A[j - gap]
j -= gap
A[j] = tmp
gap /= 2
时间复杂度
希尔排序的时间复杂度和增量序列有关,希尔增量时间复杂度为 O(n2) ,Hibbard增量时间复杂度为 O(n3/2) 。