【问题标题】:Relationship between number of comparisons between merge sort and merge-insertion hybrid sort归并排序与归并-插入混合排序的比较次数关系
【发布时间】:2021-11-03 19:56:08
【问题描述】:

我正在玩一个合并插入排序混合,它看起来大致是这样的:

def hybrid_sort_comparisons(arr, S):
    """
    Performs hybrid sort on `arr` with threshold `S`
    Returns (arr, number_of_comparisons)
    """
    if (len(arr) <= S):
        return insertion_sort_comparisons(arr, S)
    
    num = len(arr) // 2
    left, left_comparisons = hybrid_sort_comparisons(arr[:num],S)
    right, right_comparisons = hybrid_sort_comparisons(arr[num:],S)
    result, number_of_merge_comparisons = merge_comparisons(left, right)
    return result, left_comparisons + right_comparisons + number_of_merge_comparisons

这是归并排序,但基本上如果数组大小小于阈值 S(我使用 7),我们将使用插入排序,因为它在较小的数组上开销较小。

我对混合排序函数进行了一些探索性分析 - 改变数组的大小,并记录混合排序和合并排序对数组进行完全排序所需的平均比较次数。

这里是归并排序和插入排序的比较次数

这是有道理的,因为比较的次数应该随着要排序的数组大小的增加而增加。

现在,有趣的是当我试图计算归并排序和混合排序之间比较次数的差异时。这是我发现的:

我知道混合排序通常比归并排序平均需要更多的比较(因为混合排序部分大约需要 $O(nS + n \log \frac{n}{S})$ 比较,而纯归并排序需要 $O(n log n)$,所以我期待看到一条上升趋势的平滑曲线。

但是,似乎有些地方不太直接。似乎曲线上下反弹,每次连续反弹看起来都是前一次反弹的两倍。我的猜测是它与 $n/S$ 以及将 $n$ 元素均匀拆分为大小为 $S$ 的偶数列表的能力有关,但是我无法向自己严格证明这一点。

我想知道为什么会出现这种模式。

tl;dr:使用了混合合并-插入排序,当数组足够小时,我会使用插入排序,否则我会使用普通合并排序。

当我比较 numberOfComparisonsForHybridSort - numberOfComparisonsForMergeSort 时,它形成了这种以 ~$2^n$ 为增量下降的漂亮模式,但是我想知道这背后发生了什么。

【问题讨论】:

  • 您能否使图像边框不那么暗,并且不仅绘制比较的差异,还绘制两个单独的计数?

标签: python sorting mergesort insertion-sort


【解决方案1】:

考虑从运行大小为 1 或 7 开始,直到达到数组大小所需的合并“步骤”数。对于纯归并排序,它是 1->2->4->8-> ... -> >= n。对于您的混合排序,它是 7->14->28->56 ... -> => n,加上通过插入排序运行的排序上限(n/7)的开销。如果数组大小等于或略小于 2 乘以 7 的幂,则混合排序可能需要较少的比较。

大多数库对插入排序使用较大的大小,通常为 16 到 96。Visual Studio 使用 32。

【讨论】:

    猜你喜欢
    • 2021-02-03
    • 2010-12-03
    • 2016-10-02
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    相关资源
    最近更新 更多