算法 – 在文件中查找k个最常见的单词 – 内存使用

假设你给了一个巨大的文件,说1GB.该文件在每一行中包含一个单词(总共n个单词),并且您想要查找文件中k个最常用的项.

现在,假设你有足够的内存来存储这些单词,那么在减少内存使用和Big-O复杂度的不断开销方面来处理这个问题的更好的方法是什么?我相信有两种基本的算法可以使用:

>使用哈希表和最小堆来存储发生的事件和前K个字.这是O(n nlogk)〜O(N)
>使用特里来存储单词和事件,然后遍历特技来计算最常用的单词.这是O(n * p)〜O(N)其中p是最长字的长度.

哪一种更好的方法?

另外:如果你没有足够的内存用于散列表/ trie(即10MB左右的有限内存),那么最好的方法是什么?

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

这两种方法都是有效的,我认为,如果选择其他方式,如最高latency(如果是实时系统),吞吐量和开发时间,则应该考虑多种考虑因素.

如果平均情况下的性能很重要,我建议生成一堆文件并运行statistical analysis哪种方法更好. Wilcoxon签名测试是事实上使用的艺术假设测试.

关于嵌入式系统:两种方法仍然有效,但在这里:
特里中的每个“节点”(或一堆节点)将在磁盘上而不是RAM上.请注意,这意味着随机访问磁盘寻找每个条目,这可能是慢的O(| S |).

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

请注意,如果仍然不够,我们可以重新指定指针表,非常类似于paging table在虚拟内存机制中所做的工作.

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

PS,radix tree通常更快,更紧凑,然后是trie,但遭受与哈希表相比较的trie相同的副作用(尽管当然不太重要).

转载注明原文:算法 – 在文件中查找k个最常见的单词 – 内存使用 - 代码日志