【问题标题】:Mergesort to sort three input arraysMergesort 对三个输入数组进行排序
【发布时间】:2011-01-22 23:28:07
【问题描述】:

合并算法通过重复比较两个输入数组的最小元素并将两个输入数组中较小的一个移动到输出,将两个已排序的输入数组合并为一个已排序的输出数组。

现在我们需要将三个相同长度的已排序输入数组(A1、A2、A3)合并为一个(已排序)输出数组,有两种方法:

  1. 使用上述Merge算法将A1和A2合并成A4,然后用同样的算法将A4和A3合并成输出数组。

  2. 修改上述 Merge 算法,通过反复比较三个输入数组的最小元素,并将三个中最小的一个移动到输出数组。

如果只考虑数组元素移动(即赋值)的最坏情况,上述两种算法中哪一种更有效?

如果只考虑数组元素比较的最坏情况,上述两种算法哪个更有效?

在这两种算法之间,哪一种在最坏情况下的整体效率更高?

【问题讨论】:

  • “请详细说明”?真的吗?
  • 这看起来很可疑,像是从家庭作业中复制/粘贴的。没有人可能你这样做,但如果你解释你目前所理解的,有些人可能会告诉你你是对还是错。请表现出一些努力。
  • @Bill-the-Lizard:你撞到了它的鼻子。

标签: algorithm arrays sorting performance asymptotic-complexity


【解决方案1】:

如果您只关心数组写入的次数,那么第二个版本(三向合并)比第一个算法(双向合并的两个实例)更快。三路合并算法将执行 3n 次写入(其中 n 是任何序列的长度),因为它一次合并所有三个范围。第一种方法会将两个范围合并在一起,执行 2n 次写入,然后将该序列与第三个序列合并,执行 3n 次写入,总共 5n 次写入。

更一般地说,假设您有 k 个元素范围,所有元素的长度都为 n。如果您成对合并这些范围,然后再次成对合并这些合并,等等,那么您将大致执行 k/2 个合并步骤,合并长度为 n 的范围,然后合并长度为 2n 的范围的 k/4 个合并,然后合并 k/8 个长度 4n 等。这给出了总和

kn/2 + kn/2 + ... + kn/2 (log n 次)

对于 O(kn lg n) 的净数组写入次数。另一方面,如果您在每一步都使用 k-way 比较,则您会执行 kn 次写入,这要小得多。

现在,让我们考虑一下您在每个设置中进行了多少次比较。在三路合并中,写入输出序列的每个元素都需要找到三个值中的最小值。这需要两次比较 - 一次比较前两个序列的第一个值,一次比较这两个值中的最小值与第三个数组的第一个值。因此,对于写入结果序列的每个值,我们使用两次比较,由于写入了 3n 个值,我们总共需要进行最多 6n 次比较。

一个更好的方法是将序列存储在一个最小堆中,其中序列通过它们的第一个元素进行比较。在每一步中,我们将具有最小第一个值的序列从堆中出列,将该值写入结果,然后将序列的其余部分排入堆中。对于 k 个序列,这意味着写出的每个元素最多需要 O(lg k) 次比较,因为堆插入在 O(lg k) 中运行。这给出了 O(kn lg k) 的净运行时间,因为写出的每个 kn 元素都需要 O(lg k) 处理时间。

在另一个版本中,我们首先进行标准的双向合并,这需要对每个写入的元素进行一次比较,总共进行 2n 次比较。在合并的第二遍中,在最坏的情况下,我们总共进行了 3n 次比较,因为有 3G 元素被合并。这给出了总共 5n 次比较。如果我们使用上面描述的成对合并的广义构造,我们将需要使用 O(kn lg n) 比较,因为写入的每个元素都需要一次比较,而我们执行 O(kn lg n) 写入。

简而言之,对于 k=3 的特定情况,对于 9n 次内存读取和写入的网络,三路合并执行 3n 次写入和 6n 次比较。迭代的双向合并进行 5n 次写入和 5n 次比较,总共净读取和写入 10n 次内存,因此三向合并版本更好。

如果我们考虑广义结构,k-way 合并执行 O(nk) 次写入和 O(nk lg k) 次比较,总共 O(nk lg k) 次内存操作。迭代的双向合并算法执行 O(nk lg n) 次写入和 O(nk lg n) 次比较,总共 O(nk lg n) 次内存操作。因此,k-way 归并对于少数长序列渐近更好,而迭代归并排序对于许多短序列更快。

希望这会有所帮助!

【讨论】:

  • 我知道这已经过时了,但是对于三重合并排序,您并不总是需要在每个步骤中进行 3 次比较。在某些情况下,您只需要 2:(1)上一步的第二个最大元素和(2)列表中的下一个值,上一步的最大元素来自该值
猜你喜欢
  • 1970-01-01
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多