基本思想:
将待排序数列划分为几个数列,对这几个数列分别进行直接插入排序
具体操作:
选取增量d(小于数列长度n),将数列划分为n/d个数列,对划分的数列进行直接插入排序
再选取一个增量d1,d1<d,重复上述步骤
直到dn = 1结束
取d=5 23 52 12 63 8 17 28 72 36 41 ---------------------------------------------- 23 17 |_______________________| 52 28 |_______________________| 12 72 |_______________________| 63 36 |_______________________| 8 41 |_______________________| 一趟排序结果: 17 28 12 36 8 23 52 72 63 41 ---------------------------------------------- 取d=2 17 12 8 52 63 |_________|________|_________|_________| 28 36 23 72 41 |________|_________|________|_________| 二趟排序结果: 8 23 12 28 17 36 52 41 63 72 --------------------------------------------- 取d=1 三趟排序结果: 8 12 17 23 28 36 41 52 63 72
时间复杂度:
很难判断准确的时间复杂度,这和选择的增量d有关系
最坏情况和平均情况一样:O(n*log(n))
稳定性:
一次插入排序是稳定的,但是希尔排序是多次插入,在不同的插入排序过程中,相同元素在各自的插入排序中位置可能会变更,所以是不稳定排序
python代码示例:shell_sort.py
def shell_sort(l): length = len(l) d = length/2 #起始增量d选取为数列的一半 while(d >= 1): for i in range(d, length): #对l[d...n-1]分别插入各组有序子序列中 j = i - d while(j >= 0 and l[j] > l[j+d]): #距离增量d的两个元素比较 tmp = l[j] l[j] = l[j+d] l[j+d] = tmp j -= d #以d为增量,继续循环比较该子序列内的元素 d = d/2 #下一增量选取 if __name__ == '__main__': l = [93,102,36,82,76,84,55,63,49,27] shell_sort(l) print('result:' + str(l)
lua代码示例:shell_sort.lua
require "math" function shell_sort(t) length = table.getn(t) d = math:floor(lenght/2) while(d >= 1) do for i = d+1, length do --对t[d...n-1]分别插入各组有序子序列中 j = i - d while(j > 0 and t[j] > t[j+d]) do tmp = t[j] t[j] = t[j+d] t[j+d] = tmp j = j - d end end d = math:floor(d/2) end end t = {93,102,36,82,76,84,55,63,49,27} shell_sort(t) for _, v in ipairs(t) do print v end