当前位置: 首页 > 知识库问答 >
问题:

为什么双向合并排序比单向合并排序更有效

安明亮
2023-03-14

我正在维基百科上阅读关于外部排序的文章,我需要理解为什么两阶段合并比一阶段合并更有效。

Wiki:但是,单次合并有一个限制。随着区块数量的增加,我们将内存分成更多的缓冲区,因此每个缓冲区都较小,因此我们必须进行许多较小的读取,而不是较少的较大读取。

因此,对于100 MB内存中的50 GB的排序,使用单个合并过程是没有效率的:磁盘需要用500个数据块中的每个数据块(我们一次从每个数据块读取100MB/501~200KB)填充输入缓冲区,这占据了大部分排序时间。使用两个合并过程解决了这个问题。然后,排序过程可能如下所示:

Run the initial chunk-sorting pass as before.
Run a first merge pass combining 25 chunks at a time, resulting in 20 larger sorted chunks.
Run a second merge pass to merge the 20 larger sorted chunks.

谁能给我一个简单的例子来理解这个概念。我对在两阶段合并中分配更多的缓冲区感到特别困惑。


共有1个答案

安博文
2023-03-14

问题是随机访问开销,平均旋转延迟约为4毫秒,平均寻道时间约为9毫秒,平均访问时间约为10毫秒,而平均传输速率约为每秒150兆字节。因此,平均访问开销与读取或写入1.5兆字节所需的时间大致相同。

大型I/O减少了访问时间的相对开销。如果一次读取或写入10兆字节的数据,开销将减少到15%。使用wiki示例100MB的工作缓冲区和25个要合并的块,再加上一个写块,即3.8MB的块,在这种情况下,随机访问开销约为39%。

在大多数PC上,可以为1GB的工作缓冲区分配足够的内存,因此26个块,每个块超过40兆字节,将随机访问开销减少到3.75%。50块大约是每个块20兆字节,随机访问开销约为7.5%。

请注意,即使有50个块,它仍然是两遍排序,第一遍使用所有1gb缓冲区进行内存排序,然后写入排序的1gb块。第二遍合并所有50个块,从而产生html" target="_blank">排序文件。

50块的另一个问题是需要一个min堆类型的方法来维护排序信息,以确定哪个块的哪个元素是50个块中最小的,并被移动到输出缓冲区。一个元素移动到输出缓冲区后,一个新元素被移动到堆中,然后堆被重新堆化,这需要大约2个log2(50)操作,或大约12个操作。这比在进行50方式合并时进行49次比较以从一组50个元素中确定最小元素的简单方法要好。堆由结构、当前元素、这是哪个块(文件位置或文件)、块中剩余的元素数、...组成。

 类似资料:
  • 双向合并排序与递归合并排序有何不同? 假设在合并排序中有5个数字需要排序8,9,1,6,4,我们按如下步骤1进行划分:{8,9,1}{6,4} 步骤2:{8,9}{1}{6}{4} 步骤3:{8}{9}{1}{6}{4} 现在合并 步骤4:{8,9}{1}{4,6} 步骤5:{1,8,9}{4,6} 第六步:{1,4,6,8,9} 但在双向合并排序中,我们将数组分为两个元素(但根据维基百科,在合并

  • 本文向大家介绍合并排序,包括了合并排序的使用技巧和注意事项,需要的朋友参考一下 合并排序技术基于分而治之。我们将整个数据集分成较小的部分,然后按排序顺序将它们合并成较大的部分。在最坏情况下它也非常有效,因为该算法在最坏情况下的时间复杂度也较低。 合并排序技术的复杂性 时间复杂度: 所有情况下为O(n log n) 空间复杂度:  O(n) 输入输出 算法 合并(数组,左,中,右) 输入- 数据集数

  • 问题内容: [http://jsperf.com/optimized-mergesort-versus- quicksort][1] 为什么这个半缓冲区合并排序的工作速度与quicksort一样快? QuickSort是: 就地虽然会占用递归(堆栈空间) 缓存友好 这一半缓冲区合并排序: 使用Buffer进行合并。 使用递归。 进行较少的比较。 我的问题是,在这种情况下,为什么半缓冲区合并排序与Q

  • 我正在尝试理解递归排序函数,它是mergesort算法的一部分。下面是我的代码,我几乎可以肯定它是正确的(通过在线课程)。 我理解合并的作用——它将每个子数组分解成两个较小的子数组,重复这个过程,直到子数组的长度为1(根据定义排序),然后合并。然而,这个排序函数用来完成这个任务的实际方法对我来说很难理解。也许是因为我不习惯递归函数,但是我想知道是否有人可以在第一次合并发生时阐明操作的顺序和参数是什

  • 我试图借助单链表编写合并排序,节点定义如下, 合并排序的工作方式如下: i、 将未排序的列表划分为n个子列表,每个子列表包含1个元素(1个元素的列表被视为已排序)。 二、。重复合并子列表以生成新排序的子列表,直到只剩下1个子列表。这将是排序列表。代码如下所示。 我像这样打入会电话, 结果是,所有负值似乎都消失了。这里有什么问题?

  • 本文向大家介绍Haskell合并排序,包括了Haskell合并排序的使用技巧和注意事项,需要的朋友参考一下 示例 有序合并两个有序列表 保留重复项: 自顶向下版本: 定义这种方式是为了清楚而非效率。 使用示例: 结果: 自下而上的版本: