我们为什么要使用n路合并?它比双向合并有什么优势?

时间:2013-02-05 17:33:58

标签: algorithm sorting

我试着阅读一些有关n路合并的文章,但却不理解这个概念。我很困惑你为什么要在双向合并中使用n路合并?就像你为什么要将数组分为3个部分,然后对它们进行排序然后进行2部分的2路合并,然后将第3部分的2路合并与此合并的2部分:)

由于

2 个答案:

答案 0 :(得分:12)

当您进行外部排序时,通常最终会有多个要合并的流。例如,假设您需要对数TB的数据进行排序,并且只有(例如)64 GB的RAM。

您通常通过读取64 GB,对其进行排序,然后将其写出来来实现。重复完整的TB级数据,为每个可以在内存中保存的“块”生成一个中间文件。有很多方法可以改进这一点,但是您通常希望的最好的方法是生成大约128千兆字节的已排序中间文件。

这会让你有许多中间文件要合并在一起 - 这个数字肯定会大于2。

如果您要定期执行此操作,您可能需要使用一些非常高端的硬件。如果您将每个中间文件放在一个单独的磁盘驱动器上(并且至少还有一个用于输出),您几乎可以肯定通过一次合并所有数据来提高速度,而不是一次只合并两个。该过程通常是I / O限制的,因此一次从(例如)8个磁盘读取的速度通常是一次仅从2个磁盘读取的速度的4倍(尽管这取决于具有那么多带宽的输出磁盘) ,这可能不是真的)。通过避免创建更多的中间文件(需要进一步合并),您的整体速度可能会提高一个更大的因素。

答案 1 :(得分:8)

在“正常”合并排序中,将数组除以2,直到达到log2n的深度,然后开始合并。两个大小为m的数组的每次合并也会进行2m次操作。

这将使您进入以下公式(在时序分析中):

n/2 * 2 + n/4 * 4 + ... 1 * n = n * log2n

现在,如果你进行三向合并,你将把数组除以3.与前一种方法的区别是双重的:

  • 分割深度现为log3n
  • 在合并期间,您需要找到最少3个元素,而不是比较2个元素。

这意味着,在最基本的实现中,您将获得这样的公式:

n/3 * 2*3 + n/9 * 2*9 + ... 1 * 2*n = 2 * n * log3n

请注意,2乘以,因为找到三个元素的最小值包含2个操作。

渐近地,这两个都是Θ(nlogn)。但是,也许(我没有尝试过)在实践中,三向合并排序会因其log3n而提供更好的性能。然而,由于n = 1000000的log2n仅为20,而相同数字的log3n为12.5,我怀疑除非n非常大,否则此优化将非常有效。


通过巧妙的实现,k-way合并确实可以对合并排序产生很好的影响。我们的想法是,一旦找到最小的k元素,您就已经知道其余k-1元素之间的关系并非最小。因此,一旦从其各自的列表中消耗该最小元素,您只需要比较该列表的新值并找到与剩余的k-1元素相关的排序。使用堆,这将是非常简单的。


请务必同时查看Jerry's answer。我同意他的看法,多路合并的真正威力来自于处理多个磁盘和并行处理。