使用C ++删除大型文本文件中重复行的最有效内存方法是什么?
让我澄清一点,我不是要求代码,只是最好的方法。重复的行不保证是相邻的。我意识到针对最小内存使用而优化的方法会导致速度变慢,但这是我的限制因为文件太大了。
答案 0 :(得分:6)
我会散列每一行,然后寻找具有非唯一散列的行并单独比较它们(或以缓冲方式)。这对于重复出现率相对较低的文件很有用。
当你使用哈希时,你可以将使用的内存设置为一个恒定的数量(也就是说,你可以有一个只有256个插槽或更大的小型哈希表。在任何情况下,mem的数量都可以限制为任何常量。)表中的值是具有该散列的行的偏移量。所以你只需要line_count * sizeof(int)加上一个常量来维护哈希表。
更简单(但速度更慢)是扫描每行的整个文件。但我更喜欢第一种选择。这是最有效的内存选项。你只需要存储2个偏移和2个字节来进行比较。
答案 1 :(得分:3)
如果您有无限(或非常快)的磁盘I / O,您可以将每行写入其自己的文件,文件名为散列+一些标识符指示顺序(或者没有顺序,如果顺序不相关)。通过这种方式,您可以将文件系统用作扩展内存。这应该比重新扫描每行的整个文件快得多。
作为以下所述内容的补充,如果您期望高重复率,则可以在内存和文件中保留一些哈希阈值。这将为高重复率提供更好的结果。由于文件太大,我怀疑n^2
在处理时间上是可以接受的。我的解决方案是处理速度为O(n)
,内存中为O(1)
。但是,在运行时使用的所需磁盘空间中O(n)
,其他解决方案没有。
听起来您可能在各种规格的有限硬件上运行,因此在决定哪种方法最适合长期实施之前,您需要测试一些重复的删除算法和配置文件。
答案 2 :(得分:2)
您可以使用I / O高效排序(如unix排序命令),然后逐行读取文件,将每行与先前读取的行进行比较。如果两者相等则如果它们不输出该行则不输出任何内容。
这样算法使用的内存量是不变的。
答案 3 :(得分:2)
简单的暴力解决方案(内存消耗很少): 执行n ^ 2传递文件并删除重复的行。速度:O(n ^ 2),记忆:常数
速度快(但内存消耗不佳): Stefan Kendall的解决方案:散列每一行,将它们存储在某种地图中并删除已存在的行。速度:O(n),记忆:O(n)
如果您愿意牺牲文件订单(我假设没有,但我会添加它): 您可以对线进行排序,然后通过删除重复项。速度:O(n * log(n)),记忆:常数
编辑: 如果您不喜欢排序文件内容或尝试维护唯一哈希但可以处理O(n)内存使用的想法:您可以使用32位或64位位置标记(取决于文件的大小)识别每一行并排序文件位置而不是文件内容。
编辑#2:警告:内存排序不同长度的线比说它更难说,一组int ...实际上,考虑内存如何在合并步骤中移动和移动,我是第二个猜测我能够在n * log(n)
中对文件进行排序的能力答案 4 :(得分:2)
为什么不咨询Knuth, Sorting and Searching?这将为你做出平衡决定提供一个很好的背景。