参考:
百度百科:希尔排序
希尔排序(shell sort)
工作原理
直接插入排序的改进,设置步长,对间隔步长大小的数据进行直接插入排序,不断减小步长,直至步长大小为 1
。也称为缩小增量排序
算法思想
通常初次设置步长大小为 n/2,之后每次取步长大小的一半,每次均对序列进行遍历,对间隔步长大小的数据进行直接插入排序
Python 算法实现
# -*- coding: utf-8 -*-
"""
希尔排序实现
"""
import random
import math
__author__ = 'zj'
def create_data(leng, min, max):
"""
创建待排序序列
:param leng: 序列长度
:param min: 最小值
:param max: 最大值
:return: 列表
"""
li = range(min, max)
return random.sample(li, leng)
def shell_sort(li, reverse=False):
"""
希尔排序实现
:param li: 待排序列表
:param reverse: 是否从大到小排序,默认为False
:return: 已排序列表
"""
step = int(math.ceil(len(li) / 2))
while step > 0:
for i in xrange(step):
idx_list = [x for x in xrange(len(li)) if (x - i) % step == 0] # 获取间隔为 d 的下标
for j in xrange(1, len(idx_list)): # 遍历同一组子序列
for k in xrange(j):
if reverse:
if li[idx_list[k]] < li[idx_list[j]]:
li[idx_list[k]], li[idx_list[j]] = li[idx_list[j]], li[idx_list[k]]
else:
if li[idx_list[k]] > li[idx_list[j]]:
li[idx_list[k]], li[idx_list[j]] = li[idx_list[j]], li[idx_list[k]]
if step == 1:
step = 0
else:
step = int(math.ceil(step / 2))
return li
if __name__ == '__main__':
da = create_data(10, 30, 60)
print da
shell_sort(da, True)
print da
性能分析
稳定性
希尔排序是不稳定排序算法
由于每次遍历时,只对间隔步长大小的数据进行直接插入排序,所以可能导致相同大小数据的相对位置发生变化
比如,待排序序列为 (4,0)(3,1)(4,2)(2,3)(2,4)
- 首次设置步长为
3
,那么子序列为(4,0)(2,3)
,(3,1)(2,4)
,(4,2)
排序结果为 (2,3)(2,4)(4,2)(4,0)(3,1)
- 第二次设置步长为
1
,那么直接对整个序列进行插入排序
排序结果为 (2,3)(2,4)(3,1)(4,2)(4,0)
由结果可知,值为 4
的数据的相对位置发生了变化
时间复杂度
网上找了比较多的希尔排序的时间分析,没有一个统一的意见
最坏时间复杂度为 O(n*log2n)
平均时间复杂度均为 O(n^1.5)
空间复杂度
空间复杂度为 O(1)