1、定义
是插入排序的改进版
- 首先选取一个间隔,假设为4,则从原序列中,从0索引开始,下一个选4索引,再选8索引组成一个新的序列;1索引、5索引、9索引。。。组成一个新序列,以此类推,将所有元素组成新的序列。
- 然后每个序列使用插入算法,进行排序,排序后,将排过的序列按照索引放回原来的大序列中;
- 再按照间隔为2的方式取元素,组成新序列;
在新序列中再按照插入法进行排序,排好后再将这个序列中的元素按照索引放入原来的大序列中; - 这时将间隔调整为1,这时就只分为了一个序列,对此序列执行插入算法,即完成排序。
2、python实现
def shell_sort(alist):
n=len(alist)
# gap=间隔,//表示取整,%表示取余,/为除(得到小数)
gap=n//2
# gap从最大值一直取到1
while gap>0:
# 这里使用插入算法,但是是从gap索引开始,步长为1
# 即外层循环是gap开始,依次遍历之后的每个元素,直到最后一个元素
for j in range(gap,n):
# j=[gap,gap+1,gap+2.....n-1]
i=j
# 内层循环在每个小序列中进行,步长为gap,依次向前遍历
while i > 0:
if alist[i]<alist[i-gap]:
alist[i],alist[i-gap]=alist[i-gap],alist[i]
i -= gap
else:
break
# 这个步长下,所有元素遍历一次后,修改步长
# gap=gap//2
gap //= 2
if __name__ == '__main__':
list=[32,54,36,86,55,80,98,2,4,53,9]
print(list)
shell_sort(list)
print(list)
结果:
[32, 54, 36, 86, 55, 80, 98, 2, 4, 53, 9]
[2, 4, 9, 32, 36, 53, 54, 55, 80, 86, 98]
3、时间复杂度
- 最优时间复杂度:根据步长序列的不同而不同
- 最坏时间复杂度:O(n2)
- 稳定性:不稳定(因为内循环是根据步长进行排序,所以很有可能相同的值前后位置发生变化,所以是不稳定的)