从硬盘中排序巨大的整数

时间:2010-10-25 07:16:40

标签: algorithm

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

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

6 个答案:

答案 0 :(得分:7)

正如其他人所说,你可以使用O(n)counting sort。但是,您还需要考虑一些其他问题。我们假设你存储了32位整数,所以100GB~27e9整数。

如果所有整数都相同,那么它将发生~27e9次,这大于32位int。因此,您的计数器必须是64位整数。

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

  • 单独增加HD上的计数器,或
  • 忽略我们遇到的所有不在我们当前存储在RAM中的计数器数组中的整数。

我认为后一种选择更好。由于我们需要~4e9 64位计数器并且只能存储2GB,我们需要遍历整个阵列~16次。如果我们考虑遇到诸如0,1 <&lt; 31,0的整数序列,则第一种选择显然是不好的。这些计数器不会同时存储在RAM中,因此至少需要2次HD写入。

因此,我认为对于问题的具体大小(100GB),N-way merge排序会更好,因为这只需要读取整个数组log_2(100)~8次。

然而,如果面试官立即将问题改为“10TB阵列,仍然是2GB内存”,那么计算排序很容易就会获胜。

答案 1 :(得分:4)

由于要排序的数据是整数类型(4个字节),数据量是100 GB(GB为2 ^ 30),因此您需要排序26,843,545,600个整数。由于您有4,294,967,296个可能的整数值,因此您可以将此数据表示为充当计数器的long数组,这将占用大约34 GB的磁盘空间。读取100 GB的数据一次,为每个可能的整数值递增单个计数器(300 GB总磁盘访问量以读取值,读取计数器,写入递增的计数器),然后按顺序读取计数器,写出数字您读取的每个值的值(134 GB总磁盘访问量)。

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

答案 2 :(得分:3)

我认为快速算法另外100GB的免费硬盘空间是前提条件。

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

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

答案 3 :(得分:3)

对我来说,这个问题的答案很大程度上取决于文件中数字的预期分布。

在100 Gigs的int数据中有125亿个整数。 还有大约4.3亿个不同的投注。

鉴于在所有可能的整数中分布完全均匀,您可能希望每个int显示大约3次给予或接受。这种低级别的复制并不能保证从标准排序例程(一次对块进行排序然后将块合并在一起)进行更改。

但是,如果我们将“文件整数”限制为非负数,那么我们立即期望每个有效的int大约出现6次。这接近一定程度的重复,可能需要改变分类程序。因此,我认为您应该询问采访者是否可以假设有关磁盘上的整体分布的更多信息。毕竟,拥有100GB的数据并不知道它是否具有任何可预测的模式会很奇怪。

答案 4 :(得分:2)

Merge Sort在内存有限方面是一种流行的方法

答案 5 :(得分:2)

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

首先将1 Gig以下的数据读入内存,将该数据合并到内存中。刷新磁盘。重复每个内存块。然后你可以遍历每一块数据并获取所有0,重复每个整数。这需要很长时间,但这只有203GB读取和200GB写入最坏情况(理论上)。