查找并最小化合并排序算法运行时分析

时间:2018-05-08 15:21:08

标签: java arrays algorithm complexity-theory mergesort

让我说我有一个大小为n的数组,我想把它分成k个大小为n / k的新数组.- 这个步骤的运行时间可能是多少是吗?****我想我们将数组拆分为2时就像2 ^ x = n => x = log N => O(log n)那么它在这里也是一样的:k ^(n / k)= n => n / k = log N ****但接下来是什么?

现在我在每个k数组-O(n ^ 2)上运行冒泡排序算法,并且我在所有k个数组上使用合并算法来生成大小为n-let的大小的排序数组合并复杂度为O(kn)。

另外,我不想找到一个K,这样我就可以最大限度地减少算法的运行时间,我该怎么办呢?我认为运用运算符函数的衍生物并找到它的最小值就可以了,这是正确的方法吗?

2 个答案:

答案 0 :(得分:0)

合并排序将数组拆分为连续较小的块,直到它变为一堆2元素子阵列。然后它开始在连续更大的子阵列上应用合并算法。

想象一下,你有一个包含16个元素的数组。合并排序的合并方式如下:

8 merges of two 1-item subarrays
4 merges of two 2-item subarrays
2 merges of two 4-item subarrays
1 merge of two 8-item subarrays

有四个(log 2 (16))次传球,每次传球都会检查每个项目。每次通过都是O(n)。因此,此合并排序的运行时间为O(n * log 2 (n))。

现在,假设您有一个包含81个项目的数组,并且您希望使用3向合并排序合并它。现在您有以下合并序列:

27 merges of three 1-item subarrays (gives 27 3-item subarrays)
 9 merges of three 3-item subarrays (gives 9 9-item subarrays)
 3 merges of three 9-item subarrays (gives 3 27-item subarrays)
 1 merge of three 27-item subarrays

有四个(log 3 (81))次传球。每个合并为O(m * log 2 (k)),其中m是要合并的项目总数,k是列表数。所以第一遍有27个合并,进行3 * log 2 (3)比较。下一个传递有9个合并,它们执行9 * log 2 (3)比较等。最终总合并为O(n * log 3 (n) * log 2 (3))

你可以看到3向合并排序可以让你做更少的传球(3个合并排序的16个项目只需要3次传球),但每次传球都要贵一点。您需要确定的是:

n * log k (n)* log 2 (k)< n * log 2 (n)

其中k是要将数组拆分为的子数组的数量。我会让你做那个数学。

但是,你必须要小心,因为渐近分析并没有考虑现实世界的影响。例如,双向合并非常简单。当你去k路合并时k> 2,你最终不得不使用堆或其他优先级队列数据结构,这有很多开销。因此,即使上面的数学表明三向合并排序应该更快,您也希望将其与标准的双向合并进行基准测试。

更新

你是对的。如果简化方程,最终方程式是相同的。因此,无论k的值如何,计算复杂度都是相同的。

这是有道理的,因为如果k = x,那么你最终会得到堆排序。

那么你必须确定是否存在合并开销随着k增加而增加的点被减少的传递次数所抵消。您可能需要凭经验确定。

答案 1 :(得分:0)

传统上我们使用mergesort进行外部排序算法,这个问题的答案一直由一个事实支配。 mergesort需要来自多个文件的流数据并写入单个文件。瓶颈在于流式传输,而不是在CPU中。如果您尝试同时从磁盘上的太多位置流式传输,则磁盘会崩溃并开始执行随机搜索。你随机的吞吐量很糟糕。

硬件上的正确答案会有所不同(特别是如果您使用的是SSD驱动器),但traditional Unix sort确定16路合并是合理的默认设置。