希尔排序:Python语言实现

希尔排序:Python语言实现

希尔排序也称"递减增量排序",它对插入排序做了改进,将列表分成数个子列表,并对每一个子列表应用插入排序。如何切分列表是希尔排序的关键------并不是连续切分,而是使用增量 i(有时称作步长)选取所有间隔为 i 的元素组成子列表。

以下图中的列表为例,这个列表有 9 个元素。如果增量为 3,就有 3 个子列表,每个都可以应用插入排序,结果如后面的图所示。尽管列表仍然不算完全有序,但通过给子列表排序,我们已经让元素离它们的最终位置更近了。

下展示了最终的插入排序过程。由于有了之前的子列表排序,因此总移动次数已经减少了。本例只需要再移动 4 次。

如前所述,如何切分列表是希尔排序的关键。后面的代码实现中的函数采用了另一组增量。先为 <math xmlns="http://www.w3.org/1998/Math/MathML"> n 2 \frac{n}{2} </math>2n个子列表排序,接着是 <math xmlns="http://www.w3.org/1998/Math/MathML"> n 4 \frac{n}{4} </math>4n 个子列表。最终,整个列表由基本的插入排序算法排好序。下图展示了采用这种增量后的第一批子列表。

python 复制代码
def shell_sort(alist):
    sublistcount = len(alist) // 2
    while sublistcount > 0:
        for startposition in range(sublistcount):
            gap_insertion_sort(alist, startposition, sublistcount)

        sublistcount = sublistcount // 2

def gap_insertion_sort(alist, start, gap): 
    for i in range(start+gap, len(alist), gap):
        currentvalue = alist[i]
        position = i

        while position >= gap and alist[position-gap] > currentvalue:
            alist[position] = alist[position-gap]
            position = position-gap

        alist[position] = currentvalue

测试代码:

python 复制代码
a_list = [54, 26, 93, 17, 77, 31, 44, 55, 20]
print(f"before sorting: {a_list}")
shell_sort(a_list)
print(f"after sorting: {a_list}")
assert a_list == sorted(a_list)

输出:

ini 复制代码
before sorting: [54, 26, 93, 17, 77, 31, 44, 55, 20]
after sorting: [17, 20, 26, 31, 44, 54, 55, 77, 93]

性能测试:

python 复制代码
%timeit shell_sort(a_list)

结果:

sql 复制代码
1.43 μs ± 3.01 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

希尔排序的时间复杂度大概介于 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n ) O(n) </math>O(n) 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 2 ) O(n^2) </math>O(n2) 之间。若采用上面代码中的增量,则时间复杂度是 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 2 ) O(n^2) </math>O(n2) 。通过改变增量,比如采用 <math xmlns="http://www.w3.org/1998/Math/MathML"> 2 k − 1 ( 1 , 3 , 7 , 15 , 31 , ⋯   ) 2^k-1 (1, 3, 7, 15, 31, \cdots) </math>2k−1(1,3,7,15,31,⋯),希尔排序的时间复杂度可以达到 <math xmlns="http://www.w3.org/1998/Math/MathML"> O ( n 3 2 ) O(n^{\frac{3}{2}}) </math>O(n23)。

参考文档

《Python数据结构与算法分析(第2版)》:5.3.4 希尔排序

相关推荐
程序员小远5 小时前
软件测试之单元测试详解
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
心无旁骛~5 小时前
python多进程和多线程问题
开发语言·python
星云数灵5 小时前
使用Anaconda管理Python环境:安装与验证Pandas、NumPy、Matplotlib
开发语言·python·数据分析·pandas·教程·环境配置·anaconda
计算机毕设匠心工作室6 小时前
【python大数据毕设实战】青少年抑郁症风险数据分析可视化系统、Hadoop、计算机毕业设计、包括数据爬取、数据分析、数据可视化、机器学习
后端·python
计算机毕设小月哥6 小时前
【Hadoop+Spark+python毕设】智能制造生产效能分析与可视化系统、计算机毕业设计、包括数据爬取、Spark、数据分析、数据可视化、Hadoop
后端·python·mysql
程序员东岸6 小时前
《数据结构——排序(中)》选择与交换的艺术:从直接选择到堆排序的性能跃迁
数据结构·笔记·算法·leetcode·排序算法
程序员-King.6 小时前
day104—对向双指针—接雨水(LeetCode-42)
算法·贪心算法
神仙别闹7 小时前
基于C++实现(控制台)应用递推法完成经典型算法的应用
开发语言·c++·算法
Ayanami_Reii7 小时前
进阶数据结构应用-一个简单的整数问题2(线段树解法)
数据结构·算法·线段树·延迟标记
listhi5208 小时前
基于改进SET的时频分析MATLAB实现
开发语言·算法·matlab