Algorithm 从硬盘中排序大量整数

Algorithm 从硬盘中排序大量整数,algorithm,Algorithm,在RAM为2GB的硬盘上,给定100GB的整数数据,如何以最少的磁盘操作对整数进行排序。在这里,从磁盘获取一个数字被视为一个磁盘操作(尽管实际上可以获取一块数据) 我们可以在磁盘上使用额外的空间进行临时存储,不需要考虑清理临时空间的操作。 是一种流行的方法,当涉及到有限的内存 100GB的整数数据时,意味着您将有大量的重复数据。如果我试图最小化磁盘I/O,我个人会选择(bucketsort/selection)/mergesort方法作为我的第一直觉 首先将低于1G的数据读取到内存中,然后对内存

在RAM为2GB的硬盘上,给定100GB的整数数据,如何以最少的磁盘操作对整数进行排序。在这里,从磁盘获取一个数字被视为一个磁盘操作(尽管实际上可以获取一块数据)


我们可以在磁盘上使用额外的空间进行临时存储,不需要考虑清理临时空间的操作。

是一种流行的方法,当涉及到有限的内存

100GB的整数数据时,意味着您将有大量的重复数据。如果我试图最小化磁盘I/O,我个人会选择(bucketsort/selection)/mergesort方法作为我的第一直觉


首先将低于1G的数据读取到内存中,然后对内存中的数据进行合并排序。刷新到磁盘。对每个内存块重复此操作。然后您可以遍历每个数据块并获取所有0,对每个整数重复。这将需要很长时间,但这只是203GB读取和200GB写入的最坏情况(理论)。

我认为快速算法和100GB可用硬盘空间是先决条件

只需对2GB块使用任何排序,然后将它们放回原处。现在,文件中有50个已排序的块,可以使用Mihir建议的合并排序。在填充输出文件时写入输出缓冲区。您只需微调输入和输出缓冲区大小


有一些关于计数的解决方案。它不能用于如此大的范围和最大可能的计数。您只能在磁盘上存储QWORD计数器,但这意味着要进行许多随机访问,这肯定比使用更大的缓冲区慢。

对我来说,这个问题的答案主要取决于文件中数字的预期分布

100千兆字节的整数数据中有125亿整数。 还有大约43亿个不同的整数

如果在所有可能的整数上都有一个完全均匀的分布,你会期望每个整数显示大约3次“给”或“拿”。这种低水平的重复不保证改变标准的排序例程(一次对块进行排序,然后将块合并在一起的例程)


但是,如果我们限制“文件int”都是非负的,那么我们立即期望每个有效int出现大约6次。这正接近重复的程度,可能需要改变排序例程。所以,我想你应该问问面试官,关于INT在磁盘上的分布,是否还有更多的假设。毕竟,拥有100GB的数据并且不知道它是否显示出任何可预测的模式是很奇怪的。

因为被排序的数据是整数类型(4字节),数据量是100GB(其中GB是2^30),所以需要排序的整数是26843545600个。由于您有4294967296个可能的整数值,因此可以将此数据表示为用作计数器的long数组,这将消耗大约34 GB的磁盘空间。读取100 GB数据一次,增加每个可能整数值的单个计数器(300 GB总磁盘访问以读取值、读取计数器、写入增加的计数器),然后依次读取计数器,写出每个值的读取值数(134 GB总磁盘访问)


这将使用总共434 GB的磁盘访问对数据进行排序。如果您使用RAM存储整数值计数器范围的一部分,从技术上讲,您可以进一步降低磁盘访问量。

正如其他人所指出的,您可以使用O(n)。然而,还有一些额外的问题需要考虑。我们假设您存储的是32位整数,所以100GB~27e9整数

如果所有整数都相同,那么它将出现约27e9次,这比32位整数大。因此计数器必须是64位整数

使用2GB的RAM,您一次只能在RAM中存储~125e6个计数器。如果我们不能对整数的分布做出任何假设,我们必须:

  • 单独增加硬盘上的计数器,或
  • 忽略当前存储在RAM中的计数器数组中没有的所有整数

我认为后一种选择更好。由于我们需要~4e9 64位计数器并且只能存储2GB,因此我们需要在整个阵列中运行~16次。第一个选项显然是不好的,如果我们考虑遇到一个整数序列,例如0. 1,这是一种作业吗?并放入一些您尝试过的代码?See和@FosterZ:不,这不是家庭作业:)@Gabe:这个问题几乎是重复的,但这个问题强调的是减少磁盘操作。所以我想说它不是完全重复的。合并排序需要O(n)个额外的内存。您试图最小化磁盘操作,并且对CPU操作没有限制。如果在O(n^2)CPU时间内进行合并,则可以在O(1)额外空间内进行合并。不过,就我个人而言,我只需要读入2GB并对其进行快速排序。这是真的,在选择排序阶段,它确实略微优化了磁盘使用率。我认为基于RAM的排序并不重要。我们可以使用Heapsort,以恒定的额外内存使用量,并且不会出现快速排序的最坏情况。我选择heapsort,因为它在原地。我会选择一个纯粹的合并排序。O(1)主内存空间(将排序后的输出流式传输到辅助内存),因此整个内存可用于输入/输出缓冲(大块读取/写入)。我不明白Gabe提到的O(n^2)是从哪里来的,合并是O(n)。这实际上是面试问题,面试官可能很想看看如何解决这个问题。因此,我们不应该期望数据中出现某种模式。无论如何,在这个问题上,我想知道在现实生活中是否有必要对如此大量的数据进行排序。是的,我知道你写出了实际的面试问题。但是你应该在面试中询问文件中的数字是来自同一个发行版还是其他发行版