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

finding and minimizing merge sort algorithm runtime analysis

假设我有一个大小为 n 的数组,我想将它占卜为 k 个大小为 n/k 的新数组。-运行ning 时间是多少这一步可能是?****我想,因为当我们将一个数组拆分为 2 时,我们会像 2^x=n =>x=log N => O(log n) 这样看它,那么它在这里也一样工作: k^(n/k)=n => n/k=log N **** 但接下来是什么?

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

此外,我不想找到一个 K 来最小化算法的 运行time,我该怎么做?我想取 运行time 函数的导数找到它的最小值就可以了,这是正确的方法吗?

合并排序将数组拆分成连续的小块,直到它变成一堆 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

有四 (log2(16)) 遍,并且在每一遍中它检查每个项目。每次通过都是 O(n)。所以这个归并排序的运行时间是O(n * log2(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

有四 (log3(81)) 次通过。每次合并都是O(m * log2(k)),其中m是要合并的项目总数,k是列表数。所以第一遍有 27 次合并,进行 3*log2(3) 次比较。下一遍有 9 次合并,执行 9*log2(3) 次比较等。最终总合并为 O(n * log3(n) * log2(3))

您可以看到 3 向归并排序可以减少遍数(16 个项目的 3 向归并排序只需要 3 遍),但每遍的成本要高一些。您必须确定的是:

n * logk(n) * log2(k) < n * log2(n)

其中 k 是您要将数组拆分成的子数组的数量。我会让你算一下。

不过你必须要小心,因为渐近分析没有考虑现实世界的影响。例如,2 路合并非常简单。当您进行 k > 2 的 k 路合并时,您最终不得不使用堆或其他优先级队列数据结构,这会产生相当大的开销。因此,即使上面的数学告诉您 3 向归并排序应该更快,您仍需要将其与标准的 2 向归并进行比较。

更新

你是对的。如果你简化方程式,你最终会得到相同的方程式。所以无论k值如何,计算复杂度都是一样的。

这是有道理的,因为如果 k = x,那么您最终会进行堆排序。

因此,您必须确定是否存在随着 k 增加而增加的合并开销被减少的遍数所抵消的点。您可能需要根据经验来确定。

传统上我们使用合并排序作为外部排序算法,这个问题的答案一直由一个事实主导。合并排序需要从多个文件流式传输数据并写入单个文件。瓶颈在流式传输中,而不是在 CPU 中。如果您尝试一次从磁盘上的太多位置流式传输,则磁盘会损坏并开始进行随机查找。您的随机搜索吞吐量很糟糕。

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