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

外部合并排序算法是如何工作的?

隗俊誉
2023-03-14

我正在尝试理解外部合并排序算法是如何工作的(我看到了相同问题的一些答案,但没有找到我需要的东西)。我正在阅读Jeffrey McConnell的《算法分析》一书,我正在尝试实现那里描述的算法

例如,我有输入数据:3,5,1,2,4,6,9,8,7,我只能将4个数字加载到内存中。

我的第一步是以4个数字块读取输入文件,在内存中对它们进行排序,然后将其中一个写入文件A和文件B。

我得到:

A:[1,2,3,5][7]  
B:[4,6,8,9]

现在我的问题是,如果这些文件中的块不适合内存,我如何将它们合并到更大的文件中?Jeffrey McConnell写道,我需要读取一半的块并将它们合并到下一个文件C和D。

但我搞错了顺序:

C:[1,2,4,6,3,8,5,9]
D:[7]

有人能提供一个循序渐进的例子吗?

PS:我了解如何通过从文件中读取逐个数字进行合并,但如何使用内存缓冲区来减少I/O操作?

共有3个答案

蔡修远
2023-03-14

您将同时遍历文件。

只需从每个文件的开头开始,不断选取不大于(即小于或等于)另一个文件的元素,将该元素输出到新文件并增加迭代器。

从你上次的陈述来看,不清楚你是否已经知道要这么做,但这就是你需要做的,因为:

>

您只需要读取每个文件一次,因为在此过程中,您可以将文件保持在正确的位置打开,这样您就不需要再次读取整个文件才能到达正确的位置。

因此,对于:

A:[1,2,3,5]
B:[4,6,8,9]

您将从每个文件中的第一个元素开始-14

1较小,因此您可以将其输出到新文件,然后转到2

2小于4,因此您可以输出该值并转到3

3小于4,因此您可以输出该值,然后转到5

4小于5,因此您可以将其输出并转到6

56小,所以您可以输出它,然后到达A的末尾。

现在只需输出B的其余部分:6,8,9

这将为您提供[1,2,3,4,5,6,8,9]

罗烨霖
2023-03-14

首先,通过对4个数字的部分进行排序,你应该得到3个块。

A:[1,2,3,5]  
B:[4,6,8,9]
C:[7]

然后,您将读取每个文件的一半(忽略C,因为它不适合)并合并它们。因此,您将加载到内存{[1,2],[4,6]}。您将进行一次临时合并,并将结果写入一个新的块D中:

Compare 1 and 4 -> D:[1]
Compare 2 and 4 -> D:[1, 2]

现在RAM中的A部分完成了合并,所以现在您必须将其后半部分放入内存中。现在您的内存将有{[3,5],[4,6]}。

Compare 3 and 4 -> D:[1, 2, 3]
Compare 5 and 4 -> D:[1, 2, 3, 4]
Compare 5 and 6 -> D:[1, 2, 3, 4, 5]

所有块A都被合并了,所以现在只需将B的其余部分附加到D中

D:[1,2,3,4,5,6,8,9]

现在,你必须对块C和块D进行同样的处理。记住,在另一个例子中,C可以有多个数字。通过合并C和D,您将得到一个新的块E,它将是最终排序的文件。

另外,请注意,在一个更大的示例中,您可能需要更多的合并阶段。例如,如果您有20个数字要排序,您将创建5个4个数字的块,然后每次合并和合并其中两个,生成2个8个数字的块(加上4个数字中的一个额外的),然后将较新的块合并为16个数字中的一个,依此类推。

鞠自明
2023-03-14

我想经过这么长时间,你一定得到了答案。但我仍在提供一些示例链接,以帮助遇到这个问题的其他人。

注意:在研究此链接之前,您应该对堆数据结构有一个想法,看看双向排序示例和多路外部排序示例,您将获得外部排序算法实现的完整想法

 类似资料:
  • 我在理解外部排序算法中的合并步骤时遇到了一定的困难。我在维基百科上看到了这个例子,但我无法理解。 外部排序的一个例子是外部合并排序算法,它对每个适合RAM的块进行排序,然后将排序后的块合并在一起。例如,对于仅使用100 MB RAM对900 MB数据进行排序:1)读取主内存中的100 MB数据,并通过一些常规方法进行排序,如快速排序。2) 将排序后的数据写入磁盘。3) 重复第1步和第2步,直到所有

  • 我正在尝试实现一个不能正常工作的mergesort算法。合并排序的工作方式如下: i、 将未排序的列表划分为n个子列表,每个子列表包含1个元素(1个元素的列表被视为已排序)。 ii.重复合并子列表以产生新排序的子列表,直到只剩下1个子列表。这将是已排序的列表。下面提供了实现。 最初,递归调用此方法,直到只有一个元素。 这是提供的合并方法。 这里的问题是什么? 输入是输出是

  • 问题是关于从16:43到23:34的视频中的合并排序http://youtu.be/M814OagXWTI?t=16m43s 在退出左/右排序合并递归后,我不清楚我们是如何合并回这些子数组的。让我们从最底部开始,当我们的元素被分成两个子数组时,一个左子数组称为B,一个右子数组称为C。在16:43左右,我们跳转到合并函数,对数组B和C进行排序,这两个数组只有8和3。合并排序函数(下面的代码)基本上通

  • 上一章介绍了很多排序算法, 插入排序、选择排序、 归并排序等等,这些算法都属于 内部排序算法,即排序的整个过程只是在内存中完成。而当待排序的文件比内存的可使用容量还大时,文件无法一次性放到内存中进行排序,需要借助于外部存储器(例如硬盘、U盘、光盘),这时就需要用到本章介绍的 外部排序算法来解决。 外部排序算法由两个阶段构成: 按照内存大小,将大文件分成若干长度为 l 的子文件(l 应小于内存的可使

  • 我很难理解递归合并排序算法是如何工作的,我理解它在理论上是如何工作的:如果一个数组中有多个元素,找到它的中间,将数组分成两个较小的子数组,依此类推,直到你有两个1个元素的数组,根据定义已经排序(基本情况),然后你可以使用合并算法合并它们,然后你爬上树,依此类推。 我试着用python实现它,用一些print语句一步一步地执行,它是可行的,但我真的不明白为什么它会这样工作。我将向你描述我的错误逻辑:

  • 我知道合并排序算法的基本概念,但是当涉及到通过递归实现它时,我很难理解它是如何工作的。据我所知,合并排序函数将我们当前的数组分成两半,并使用递归我们一直这样做,直到每边只剩下一个元素。 如果我们的数组是{38、27、43、3、9、82、10},那么我们的递归将从使用子数组(原始数组的左侧)调用自身开始,并每次重复该过程,将数组减半并存储最左侧,直到达到1个元素: 然后在我们的第二个子例程中,我们继