码迷,mamicode.com
首页 > 编程语言 > 详细

希尔排序(Shell sort)

时间:2018-11-03 19:23:23      阅读:252      评论:0      收藏:0      [点我收藏+]

标签:位置   形式   img   没有   line   分析   相对   lis   int   

希尔排序,又称“缩小增量排序”,通过将原始列表分成若干个子列表来改进插入排序,每个子列表使用插入排序。
如何选择子列表的形式是希尔排序的关键。希尔排序使用增量i(有时又成为间隙gap)来创建子列表,而不是将原始列表连续的切分。这种方式可以将相隔较远,较为分散的元素通过增量划分到一组,改进了一次插入排序只能在相邻间元素进行比较。

图解实例

如下图所示,我们有9个元素,如果我们使用增量3,则可以将原始列表分成3个子列表,每个子列表3个元素。子列表为{a1, a4, a7},{a2, a5, a8},{a3, a6, a9}。然后分别对这3个子列表使用插入排序。
技术分享图片

分别进行完一次插入排序后,结果如下图。虽然这个列表没有完全排序,但发生了一些非常有趣的事情。 通过对子列表进行排序,我们将这些元素移动到更接近实际所属的位置。
技术分享图片

由上图可以看出,通过增量3,分别对3个子列表进行排序后,我们得到一个接近完全排序的列表。只有20,31,54三个元素没有得到排序,而其他元素的相对位置已经保持排序。
这次我们将增量i变为1,则此时子列表和上图中的列表相同,然后对其运用插入排序。则最终结果如下图。
技术分享图片

使用其他增量

一般情况下,我们会这样选择增量:假设列表长度为N,则一次使用N/2,N/4,......,1。下图为另一种增量的使用方式:N为9,则第一个增量为4。
技术分享图片

代码实现

def shell_sort(a_list):
    sublist_count = len(a_list) // 2
    while sublist_count > 0:
        for start_position in range(sublist_count):
            gap_insertion_sort(a_list, start_position, sublist_count)
        print("After increments of size", sublist_count, "The list is", a_list)
        sublist_count = sublist_count // 2


def gap_insertion_sort(a_list, start, gap):
    for i in range(start + gap, len(a_list), gap):
        current_value = a_list[i]
        position = i
        while position >= gap and a_list[position - gap] > current_value:
            a_list[position] = a_list[position - gap]
            position = position - gap
        a_list[position] = current_value

整个算法的实现逻辑如下:shell_sort方法为主方法,首先获取增量sublist_count用以划分子列表。每划分一次,就使用gap_insertion_sort对各个子列表进行插入排序,直至增量值变为1。值得注意的是,在gap_insertion_sort中,实现的依然是上一讲中的插入排序,只不过我们多子列表进行插入排序。在一次插入排序算法中,我们遍历的是整个列表,在子列表插入排序中,我们每间隔一个gap进行遍历。

总结

乍一看,你可能认为shell排序不能比插入排序更好,因为它在最后一步执行完整的插入排序。 然而,事实证明,这个最终插入排序不需要进行很多比较(或移位),因为列表已经被先前的增量插入排序预先排序,如上所述。换句话说,每次子列表插入排序产生一个比前一个更“排序”的列表。 这使得最后的插入排序非常迅速。
对一般的shell sort进行分析超出了本文的范畴。但我们可以说,根据上面的描述,shell sort的时间复杂度通常介于\(O(n)\)\(O(n^2)\)之间。通过改变增量,如使用\(2^k-1\)(1,3,7,15,31,......),可以将时间复杂度变为\(O(n^\frac{3}{2})\)
一次插入排序是稳定的,但希尔排序确实不稳定的。

希尔排序(Shell sort)

标签:位置   形式   img   没有   line   分析   相对   lis   int   

原文地址:https://www.cnblogs.com/jeffrey-yang/p/9901561.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!