基本算法之希尔排序(Shell Sort)
基本算法—09、希尔排序(Shell Sort)算法
。往期请看选择排序,插入排序,归并排序,快速排序等等都发布的!欢迎大家批评指正!
0、前言
评判一个算法的好坏的标准:
- 时间复杂度
- 空间复杂度
1、希尔排序算法是什么?
1959年Shell发明,第一个突破O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
希尔排序(Shell Sort)的核心在于间隔序列的设定。既可以提前设定好间隔序列,也可以动态的定义间隔序列。动态定义间隔序列的算法是《算法(第4版)》的合著者Robert Sedgewick提出的。
- Shell Sort的运行时间很大程度上取决于它使用的步长gap
- 是不稳定的排序算法
算法描述:
希尔排序将序列按固定间隔划分为多个子序列,在子序列中简单插入排序,先做远距离移动使序列基本有序;逐渐缩小间隔重复操作,最后间隔为1时即简单插入排序。
- 择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
- 按增量序列个数k,对序列进行k 趟排序;
- 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
2、算法过程图解
上面的图片一动态演示,不是特别的直观,只是显示的一个大体的过程
下图中的是是一个图片详解!
动态的演示:
3、代码实现
代码如下(示例):
"""
shell sort 希尔排序
"""
def shell_sort(alist):
# 这一个区间每次都是变成原来的1/3左右,因为后面gap*3,下面的时候又在//3取整
# 基本区间
gap = 1
while gap<len(alist):
gap=gap*3+1
while gap>0:
for i in range(gap,len(alist)):
# value = alist[i]
j = i-gap
while j>=0 and alist[j+gap]<alist[j]:
# 如果后面小于前面的,就交换
alist[j+gap],alist[j] = alist[j],alist[j+gap]
# 然后回退一个区间再次进行比较
j-=gap
# 把区间缩小1/3,当gap==1的时候就是最后的一次排序
gap//=3
return alist
if __name__ == '__main__':
alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(f'基数排序(Radix Sort)之前原列表的顺序:{alist}')
alist = shell_sort(alist)
print(f'基数排序(Radix Sort)之后的列表的顺序:{alist}')
print(f'基数排序(Radix Sort)之后的正确的顺序:[17, 20, 26, 31, 44, 54, 55, 77, 93]')
大家可以把代码放置到编译器里面,debug运行,看一哈具体的过程,结合动态图片演示理解更好!
4、评判算法
- 最好时间复杂度:O(n)
- 最坏时间复杂度:O(n 2)
- 平均时间复杂度:O(n 1.3)
- 空间复杂度:O(1)
- 算法稳定性:不稳定的排序