Sorting 外部合并排序算法

Sorting 外部合并排序算法,sorting,merge,external,Sorting,Merge,External,我在理解外部排序算法中的合并步骤时遇到了一定的困难。我在维基百科上看到了这个例子,但无法理解它 外部排序的一个例子是外部合并排序算法,它对每个适合RAM的块进行排序,然后将排序后的块合并在一起。例如,对于仅使用100 MB RAM对900 MB数据进行排序: 1) 在主存中读取100MB的数据,并通过一些常规方法进行排序,如快速排序。 2) 将排序后的数据写入磁盘。 3) 重复步骤1和2,直到所有数据都已排序为100 MB块(有900MB/100MB=9个块),这些块现在需要合并到单个输出文件中

我在理解外部排序算法中的合并步骤时遇到了一定的困难。我在维基百科上看到了这个例子,但无法理解它

外部排序的一个例子是外部合并排序算法,它对每个适合RAM的块进行排序,然后将排序后的块合并在一起。例如,对于仅使用100 MB RAM对900 MB数据进行排序: 1) 在主存中读取100MB的数据,并通过一些常规方法进行排序,如快速排序。 2) 将排序后的数据写入磁盘。 3) 重复步骤1和2,直到所有数据都已排序为100 MB块(有900MB/100MB=9个块),这些块现在需要合并到单个输出文件中。 4) 将每个已排序块的前10MB(=100MB/(9个块+1))读入主内存中的输入缓冲区,并将剩余的10MB分配给输出缓冲区。(实际上,将输出缓冲区变大而将输入缓冲区变小可能会提供更好的性能。) 5) 执行9路合并并将结果存储在输出缓冲区中。如果输出缓冲区已满,请将其写入最终排序的文件,然后清空。如果9个输入缓冲区中的任何一个为空,则用其关联的100 MB排序块中的下一个10 MB填充该缓冲区,直到该块中没有更多可用数据。


我无法理解这里的第四步。为什么在我们有100 MB可用内存的情况下要读取前10MB内存。我们如何确定外部合并的过程数?我们会对每个块进行排序并将它们存储在9个文件中吗?

假设您已将范围拆分为k个排序的元素块。如果您可以对这些已排序的块执行k-way合并并将结果写回磁盘,那么您就已经对输入进行了排序

要进行k-way合并,需要存储k个读取指针(每个文件一个),并重复查看所有k个元素,取最小的元素,然后将该元素写入输出流并前进相应的读取指针

现在,由于所有数据都存储在磁盘上的文件中,所以实际上无法存储指向尚未读取的元素的指针,因为无法将所有内容都放入主内存中

让我们从一个简单的方法开始,来模拟正常的合并算法会做什么。假设您在内存中存储了k个元素的数组。将每个文件中的一个元素读入每个数组插槽。然后,重复以下步骤:

  • 扫描阵列插槽并取最小的
  • 将该元素写入输出流
  • 通过从相应文件中读取下一个值来替换该数组元素
这种方法可以正常工作,但速度会非常缓慢。请记住,磁盘I/O操作比主存中相应的操作花费的时间要长得多。这个合并算法最终执行Θ(n)磁盘读取(我假设k远小于n),因为每次选择下一个元素时,我们都需要执行另一次读取。这将是令人望而却步的昂贵,所以我们需要一个更好的方法

让我们考虑一个修改。现在,我们不存储每个文件一个k元素的数组,而是存储一个k个插槽的数组,每个插槽保存对应文件中的第一个R元素。为了找到下一个要输出的元素,我们扫描整个数组,对于每个数组,查看我们尚未考虑的第一个元素。我们获取该最小值,将其写入输出,然后从数组中删除该元素。如果这清空了数组中的一个插槽,我们将通过从文件中再读取R个元素来补充它

这更为复杂,但它大大减少了我们需要执行的磁盘读取次数。具体地说,因为元素是以大小为R的块读取的,所以我们只需要进行Θ(n/R)磁盘读取

我们可以采取类似的方法来最小化写操作。我们存储一个大小为W的缓冲区,在运行时将元素累积到其中,并且只在缓冲区填满时才写入,而不是将每个元素一次写入一个磁盘(需要Θ(n)次写入)。这需要Θ(n/W)磁盘写入

显然,增大R和W会使这种方法运行得更快,但会以牺牲更多内存为代价。具体地说,我们需要空间让kR项存储大小为R的读缓冲区的k个副本,并且我们需要空间让W项存储大小为W的写缓冲区。因此,我们需要选择R和W,以便kR+W项适合主内存

在上面给出的示例中,您有100MB的主内存和900MB的排序空间。如果将数组拆分为9个部分,则需要选择R和W,以便(kR+W)·
sizeof(record)
≤ 100MB。如果每个项目都是一个字节,那么选择R=10MB和W=10MB可以确保所有内容都适合。这可能也是一个很好的发行版,因为它保持了较低的读写次数