查找文件中最常见的k个单词 - 内存使用情况

时间:2012-12-21 09:59:37

标签: algorithm data-structures

假设您有一个巨大的文件,比如1GB。该文件在每行包含一个单词(总共n个单词),并且您希望在文件中找到k个最常用的术语。

现在,假设您有足够的内存来存储这些单词,那么在减少内存使用量和Big-O复杂性的持续开销方面,有什么更好的方法来解决问题?我相信可以使用两种基本算法:

  1. 使用哈希表和最小堆来存储事件和看到的前K个单词。这是O(n + nlogk)~O(N)
  2. 使用trie存储单词和出现次数,然后遍历trie以计算最常用的单词。这是O(n * p)~O(N),其中p是最长单词的长度。
  3. 哪种方法更好?

    另外:如果你的哈希表/特里没有足够的内存(即10MB左右的内存有限),那么最好的方法是什么?

3 个答案:

答案 0 :(得分:5)

关于常数更有效的是非常依赖。一方面,trie为插入所有元素提供了严格的O(N)时间复杂度,而在最坏的情况下,哈希表可能会衰减到二次时间
另一方面,尝试在cache 时效率不高 - 每次搜索都需要O(|S|) 随机访问内存请求,这可能会导致性能显着下降。

这两种方法都是有效的,我认为在选择一种方法时应该考虑多种因素,例如最大latency(如果是实时系统),吞吐量和开发时间。< / p>

如果平均案例表现非常重要,我建议生成一堆文件并运行 statistical analysis 哪种方法更好。 Wilcoxon签名测试是使用中的事实上的现状假设测试。


关于嵌入式系统:这两种方法仍然有效,但在这里: trie中的每个“节点”(或节点串)将位于磁盘上而不是RAM上。请注意,对于每个条目的trie O(| S |)随机访问磁盘搜索,这意味着,这可能会很慢。

对于散列解决方案,你有10MB,假设他们可以使用5MB这些指针到磁盘指针的哈希表。我们还假设您可以在这5MB上存储500个不同的磁盘地址(这里是悲观分析),这意味着每次散列搜索后你还有5MB左右加载一个桶,如果你有500个桶,加载因子为0.5,则意味着你可以存储500 * 5MB * 0.5~ = 1.25GB&gt; 1GB的数据,因此使用哈希表解决方案,所以使用哈希 - 每次搜索只需要O(1) 随机磁盘搜索,以便找到包含相关的字符串。

请注意,如果仍然不够,我们可以重新发送指针表,非常类似于虚拟内存机制中paging table的内容。

由此我们可以得出结论,对于嵌入式系统,哈希解决方案在大多数情况下都更好(请注意,在最坏的情况下它可能仍然会遇到高延迟,这里没有银弹)。


PS, radix tree 通常比trie更快,更紧凑,但是与哈希表相比,trie具有相同的副作用(当然,虽然不太重要)。

答案 1 :(得分:0)

对于有限的内存选项,您可以先对列表进行快速排序,然后只需填充哈希表,其中包含k个项目。然后你需要一个计数器才能知道当前单词中你检查的项目数量 - 如果它更高,那么你用当前项目替换哈希表中的最低项目。

这可能对初始列表没问题,但是比扫描完整列表要慢,并用计数填充哈希表。

答案 2 :(得分:0)

您是否开车存储中间结果?如果是的话:

你可能有一些元结构。 和一套哈希表。 您读取了一部分数据(当您散列的大小<3 mb时)并填充哈希表。 而尺寸&gt; 3mb你保存在磁盘上。 如果你限制是10 MB的哈希表大小是3 MB(例如)。

meta描述你的哈希表。 在meta中,您可以存储此哈希中的所有单词的唯一单词数和计数,以及一个世界的最大计数!我

之后。 你可以从磁盘加载哈希表并合并。

例如,您可以按哈希中唯一字的升序或一个世界的最大计数加载哈希表。 在这一步中,您可以使用一些启发式方法。