概要
-IDE:Pycharm
-Python版本:python3.x
-算法分类:内部排序->插入类排序->希尔排序
算法思想
希尔排序又称缩小增量排序法,是一种基于插入思想的排序方法。它利用了直接插入排序的最佳性质,首先,将待排序的关键字序列分成若干个较小的序列,对子序列进行直接的插入排序,使整个待排序列排好序。
过程如下:
1.首先选定记录间的距离$d_i(i=1)$,在整个待排序记录序列中将所有间隔为$d_1$的记录分成一组,进行组内直接插入排序。
2.然后选取$i=i+1$,记录间的距离为$d_i(d_i<d_i-_1)$,在整个待排序记录序列中,将所有间隔为$d_i$的记录分成一组,进行组内直接插入排序。
3.重复步骤2直至记录间的距离$d_i=1$,此时整个只有一个子序列,对该序列进行直接插入排序,完成整个排序过程。
算法要点
增量取法
关于增量$d$的取法,最初希尔提出取$d=[n/2]$,再取$d=[d/2]$,直到$d=1$为止。该思路的缺点是,奇数位置的元素在最后一步才会与偶数位元素进行比较,使得排序效率低。后来Knuth提出$d=[d/3]+1$。此外还有多种取法,但无法证明那种最优。
逆转数
为了分析希尔排序的优越性,这里引入逆转数的概念。对于待排序列中的某个记录的关键字,它的逆转数是指在它之前比此关键字大的关键字个数。
假设:被调换位置的两个关键字之间有$l$个介于两个关键字之间的数。逆转数之和一定会减小$2l+1$
当逆转数为$0$时则表明整个排序完成。
稳定性与时间复杂度
排序算法 | 稳定性 | 时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 |
---|---|---|---|---|---|
希尔排序 | 不稳定 | $O(n^{1.5})$ | $O(1)$ |
Python代码清单
# !/usr/bin/python3
# _*_ coding:utf-8 _*_
# 希尔排序
import random, time, sys
def SS(number,maxNumber):
# 生成随机数
timeStart = time.time()
listA = [0] # 0位 一般都空出来,防止out of index 或者做监视哨或者备份某个值。
for i in range(number):
listA.append(random.randint(0, maxNumber)) # 添加生成的值。
timeEnd = time.time()
timeIs = timeEnd - timeStart
listD = [0, int(number/2)] # listD用于存放增量d,第0位用0占位,我们从第一位开始循环。
while True:
if listD[-1] != 1: # 判断最后一个元素(增量)是否是1,若不是继续计算增量。
listD.append(int(listD[-1]/3)+1) # 计算增量
else:
break # 若是1,则退出循环。
print('生成%d个数的时间是%f' % (number, timeIs))
# print(listA[1:]) # 从第一位开始输出。0位不显示。
# print(listD[1:]) # 输出d的增量的列表
####################################################
# 希尔排序算法。 我认为 右边是前,左边是后。
timeStart = time.time() # 开始记录时间
# 算法开始
for d in listD[1:]: # 设置循环的次数,与d有关系。
base = 1 + d # 从前向后找,从哦能通过d+1位开始。
for item in range(base, len(listA)): # 每次增加一位
if listA[item] < listA[item-d]: # 如果遇到前面小,后面大的数,
listA[0] = listA[item] # 复制前面的数
aim = item-d # 选定目标的位置。
while True: # 开始循环查询序列。
if aim > 0 and listA[0] < listA[aim]: # 这里应设置条件,以防无限循环。
listA[aim + d] = listA[aim] # 将选定目标位的数后移。
aim = aim - d # 每次向前查找,步长为d
else:
break # 条件不符合 break 出
listA[aim+d] = listA[0] # 把目标值放入目标位。加d是因为在循环时多减了d。
# 算法结束
timeEnd = time.time() # 记录结束时间。
timeIs = timeEnd - timeStart # 排序花费的时间
print('排序%d个数,花费的时间是%f' % (number, timeIs))
# print(listA[1:]) # 打印最后排序的列表。
if __name__ == '__main__':
helpInfo = '''
This program is for Shell's Sort.
How to use it! Follow the example!
python Shell's_Sort.py 10 100
The 10 representative will generate ten numbers.
100 representative the max-number you make.
'''
command = sys.argv[0:] # 获取从键盘输入的值。
if len(command) != 3 or 'help' in command: # 判断是否合法,或包含help
print(helpInfo) # 打印帮助文本。
else:
try: # 尝试将输入转化为整数。
number = int(command[1])
maxNumber = int(command[2])
except ValueError: # 数值型错误。
print(helpInfo) # 打印帮助。
sys.exit(1) # 退出程序。
SS(number, maxNumber) # 一切完好,调用函数。
有什么问题请联系我
QQ:3116316431 (请附上信息)
E-mail:wongyinlong@yeah.net