【发布时间】:2010-12-05 09:05:28
【问题描述】:
假设我有 X GB 的可用 RAM 空间,我需要对大量数据进行排序(所有可用内存要大得多。它存储在硬盘上)。能否给个提示,如何实现?
【问题讨论】:
假设我有 X GB 的可用 RAM 空间,我需要对大量数据进行排序(所有可用内存要大得多。它存储在硬盘上)。能否给个提示,如何实现?
【问题讨论】:
您正在寻找外部排序。 这些场景中最大的开销往往是磁盘 IO。所以诀窍是使用最小化磁盘 IO 的算法。 通常的方法是将适当的大块读入内存,对这些块进行排序,将它们保存回磁盘,然后合并已排序的块。
搜索“外部排序”或“排序合并”以及您选择的技术应该会得到一些不错的结果。
【讨论】:
假设您有一个巨大的文件 H 并限制内存 M。
我有两个解决方案。
解决方案 1:
第 1 步:从文件中读取 M 并将其写入临时缓冲区。
第 2 步:对值进行排序(您应该使用就地排序算法,如 QuickSort、HeapSort)。
步骤 3:创建一个临时文件并将缓冲区写入临时文件。保存临时文件的名称。
步骤4:重复步骤1到3,直到读取出文件H,并整理出M并保存所有临时文件。
第 5 步:将所有临时文件合并到一个新文件中。创建一个新文件,并打开所有临时文件,将文件句柄放入一个数组中。
步骤6:从文件读取指针当前指向的数字集合中找到最小的数字。您可以使用正常的方法来做到这一点,比较每个数字,并使用临时变量来记住它(时间复杂度为 O(n)。或者您可以创建一个 priorityQueue 和一个映射,映射的键是数字,而map的值就是文件句柄的顺序。(时间复杂度是O(lgn),第二种方式比较浪费内存,但是性能更好,如果想要更好的方式,可以用int来替换list使用位图,因为临时文件名是连续的。
第 7 步:将号码保存到新文件中。
第 8 步:从包含第 6 步中最小数字的文件中读取另一个数字。
第 9 步:重复第 7 步到第 8 步,直到处理完所有临时文件中的所有数字。
解决方案 2:
step 1:创建N个临时文件,每个临时文件的个数范围都不一样。(例如temp_file_1的范围是0到1000000,下一个临时文件是1000001到2000000...)
第 2 步:从 H 文件中读取 m 并将数字写入不同的临时文件,直到无法从文件 H 中读取任何内容。
第 3 步:对每个临时文件进行排序。
第四步:新建一个文件,将所有临时文件一个一个合并到这个新文件中。
解决方案之间有什么区别。 根据解决方案1,每个数字排序一次并进行多次比较(步骤5),但只读取和写入两次。关于方案2,没有合并处理,但是每个数字都被读写3次。
【讨论】:
您正在寻找的是外部排序。
【讨论】:
实际上,如果您不想编写太多代码,并且磁盘使用不是问题,请将您的数据放入具有适当索引的数据库中,然后从那里直接select * order by。
【讨论】:
我想你可能会构建某种索引系统,你可以将排序后的数据分离到其中。
想象一下图书馆里的书架。遍历 1/x 的数据,将所有元素排序到货架上,并将每个货架缓存到磁盘上的单个文件中。然后对下一个 1/x 的数据进行排序,将其写回磁盘等。一旦您将所有数据放在货架上,然后对每个货架进行单独排序,然后最后将它们合并到一个很好的排序文件中。
【讨论】:
您可以使用ZZZServer 对许多大文件进行排序(排序结果可以是 TB 甚至更大)。它可免费用于非商业用途。我隶属于该产品:
ZZZServer -sortinit -sort file1.txt
ZZZServer -sort file2.txt
ZZZServer -sort file3.txt
...
ZZZServer -sortsave sorted.txt
排序后的结果保存在
sorted.txt
您的输入文件必须以 UTF-8 或 ASCII 格式编码!
ZZZServer 使用大约 1MB RAM 来排序大文件!
【讨论】: