使用C ++删除文本文件中重复行的内存有效方法

时间:2010-03-18 03:13:54

标签: c++ file file-io io

使用C ++删除大型文本文件中重复行的最有效内存方法是什么?

让我澄清一点,我不是要求代码,只是最好的方法。重复的行不保证是相邻的。我意识到针对最小内存使用而优化的方法会导致速度变慢,但这是我的限制因为文​​件太大了。

5 个答案:

答案 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?这将为你做出平衡决定提供一个很好的背景。