排序算法专题之希尔排序
Posted Python算法之旅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法专题之希尔排序相关的知识,希望对你有一定的参考价值。
希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n^2)的第一批算法之一。
为什么希尔排序算法的效率会比简单插入排序高?如何理解希尔排序的算法思想?本文拟从“步长为2跳跃式冒泡排序”,到“步长为2跳跃式插入排序”,再到“步长为m跳跃式插入排序”,最后再到“希尔排序”的顺序为大家演示算法的进化过程。
扫码加入“Python算法之旅”微信群,和斌哥面对面交流,更多资料和更有趣的话题等你一起来分享。
排序算法专题之希尔排序
1. 跳跃式冒泡排序(步长为2)
例1.分别对数组a的奇数和偶数位置的元素进行冒泡排序,即采用“跳跃式冒泡”的方法,每次跳跃的步长为2,将数组分成2个子序列,分别对这2个子序列进行排序。
例如,考虑对数组a = [6, 3, 5, 4, 1, 2, 8, 7]进行跳跃式冒泡排序,
排序后的数组a = [1, 2, 5, 3, 6, 4, 8, 7]。
函数名:jump_bubble_sort(a)
参数表:a -- 待排序列表。
返回值:该方法没有返回值,但是会对列表的对象按要求排序。
def jump_bubble_sort(a):
for i in range(1, ① ): #冒泡趟数
for j in range(② ): #向左扫描
if a[j] < a[j-2]:
a[j], a[j-2] = a[j-2], a[j]
2. 跳跃式插入排序(步长为2)
例2.分别对数组a的奇数和偶数位置的元素进行插入排序,即采用“跳跃式插入”的方法,每次跳跃的步长为2,将数组分成2个子序列,分别对这2个子序列进行排序。
例如,考虑对数组a = [6, 3, 5, 4, 1, 2, 8, 7]进行跳跃式插入排序,
排序后的数组a = [1, 2, 5, 3, 6, 4, 8, 7]。
函数名:jump_insert_sort(a)
参数表:a -- 待排序列表。
返回值:该方法没有返回值,但是会对列表的对象按要求排序。
def jump_insert_sort(a):
for i in range(2, len(a)):
t, j = a[i], i - 2
while j >= 0 and a[j] > t:
① #跳跃式移动,跳跃距离为2
j -= 2
②
3. 跳跃式插入排序(步长为m)
例3.跳跃式插入排序(推广到步长为m的情形):将数组a步长为m的元素视为同组元素,将数组分成m个子序列,分别对这m个子序列进行插入排序。
例如,考虑对数组a = [6, 3, 5, 4, 1, 2, 8, 7]进行跳跃式插入排序。
当m=1时,排序后的数组a = [1, 2, 3, 4, 5, 6, 7, 8];
当m=2时,排序后的数组a = [1, 2, 5, 3, 6, 4, 8, 7];
当m=3时,排序后的数组a = [4, 1, 2, 6, 3, 5, 8, 7];
函数名:jump_insert_sort (a, m)
参数表:a -- 待排序列表。m -- 跳跃的步长
返回值:该方法没有返回值,但是会对列表的对象按要求排序。
def jump_insert_sort (a, m):
|
4. 希尔排序
例4.将相隔一定步长的元素组成一个子序列,分别对他们进行插入排序。每完成一轮分组排序后,我们就将步长减半,继续分组排序,直至步长m=1,就变成普通的插入排序了。
函数名:shell_sort(a)
参数表:a -- 待排序列表。
返回值:该方法没有返回值,但是会对列表的对象按要求排序。
def shell_sort(a):
m = len(a) // 2
while m > 0:
for i in range(m, len(a)):
t, j = a[i], i - m
while j >= 0 and a[j] > t:
① #跳跃距离为m
j -= m
a[j+m] = t
② #步长m每次减半
1. 跳跃式冒泡排序(步长为2)
例1.分别对数组a的奇数和偶数位置的元素进行冒泡排序,即采用“跳跃式冒泡”的方法,每次跳跃的步长为2,将数组分成2个子序列,分别对这2个子序列进行排序。
例如,考虑对数组a = [6, 3, 5, 4, 1, 2, 8, 7]进行跳跃式冒泡排序,
排序后的数组a = [1, 2, 5, 3, 6, 4, 8, 7]。
函数名:jump_bubble_sort(a)
参数表:a -- 待排序列表。
返回值:该方法没有返回值,但是会对列表的对象按要求排序。
def jump_bubble_sort(a):
for i in range(1, (len(a)-1) // 2 + 1): #冒泡趟数
for j in range(len(a)-1, i*2-1, -1):
if a[j] < a[j-2]:
a[j], a[j-2] = a[j-2], a[j]
2. 跳跃式插入排序(步长为2)
例2.分别对数组a的奇数和偶数位置的元素进行插入排序,即采用“跳跃式插入”的方法,每次跳跃的步长为2,将数组分成2个子序列,分别对这2个子序列进行排序。
例如,考虑对数组a = [6, 3, 5, 4, 1, 2, 8, 7]进行跳跃式插入排序,
排序后的数组a = [1, 2, 5, 3, 6, 4, 8, 7]。
函数名:jump_insert_sort(a)
参数表:a -- 待排序列表。
返回值:该方法没有返回值,但是会对列表的对象按要求排序。
def jump_insert_sort(a):
for i in range(2, len(a)):
t, j = a[i], i - 2
while j >= 0 and a[j] > t:
a[j+2] = a[j] #跳跃式移动,跳跃距离为2
j -= 2
a[j+2] = t
3. 跳跃式插入排序(步长为m)
例3.跳跃式插入排序(推广到步长为m的情形):将数组a步长为m的元素视为同组元素,将数组分成m个子序列,分别对这m个子序列进行插入排序。
例如,考虑对数组a = [6, 3, 5, 4, 1, 2, 8, 7]进行跳跃式插入排序。
当m=1时,排序后的数组a = [1, 2, 3, 4, 5, 6, 7, 8];
当m=2时,排序后的数组a = [1, 2, 5, 3, 6, 4, 8, 7];
当m=3时,排序后的数组a = [4, 1, 2, 6, 3, 5, 8, 7];
函数名:jump_insert_sort (a, m)
参数表:a -- 待排序列表。m -- 跳跃的步长
返回值:该方法没有返回值,但是会对列表的对象按要求排序。
def jump_insert_sort (a, m):
for i in range(m, len(a)):
t, j = a[i], i - m
while j >= 0 and a[j] > t:
a[j+m] = a[j] #跳跃式移动,跳跃距离为m
j -= m
a[j+m] = t
4. 希尔排序
例4.将相隔一定步长的元素组成一个子序列,分别对他们进行插入排序。每完成一轮分组排序后,我们就将步长减半,继续分组排序,直至步长m=1,就变成普通的插入排序了。
函数名:shell_sort(a)
参数表:a -- 待排序列表。
返回值:该方法没有返回值,但是会对列表的对象按要求排序。
def shell_sort(a):
m = len(a) // 2
while m > 0:
for i in range(m, len(a)):
t, j = a[i], i - m
while j >= 0 and a[j] > t:
a[j+m] = a[j] #跳跃距离为m
j -= m
a[j+m] = t
m //= 2 #步长m每次减半
Python排序算法系列文章是我在阅读了大量算法专著以后,尝试用浅陋的语言把自己的理解表达出来。由于本人水平有限,表述中难免出现疏漏甚至错误之处,敬请谅解。
无论是赞同还是反对我的看法,都请你给我留言。如果你有新的想法,千万不要憋在心里,请发出来大家一起讨论。让我们相互学习,共同进步!
需要本文word版的,可以加入“选考VB算法解析”知识星球参与讨论和下载文件,“选考VB算法解析”知识星球汇集了数量众多的同好,更多有趣的话题在这里讨论,更多有用的资料在这里分享。
我们专注选考VB算法,感兴趣就一起来!
相关优秀文章:
以上是关于排序算法专题之希尔排序的主要内容,如果未能解决你的问题,请参考以下文章