Hash 优化字数

Hash 优化字数,hash,dictionary,count,word,trie,Hash,Dictionary,Count,Word,Trie,(就目前而言,这在本质上是相当假设的,因此我没有太多细节要提供。) 我有一个随机(英语)单词的平面文件,每行一个。我需要编写一个高效的程序来计算每个单词出现的次数。这个文件很大(可能是1GB左右),但我有足够的内存。它们存储在永久介质上,所以读取速度很慢,所以我只需要线性地读取一次 我脑子里的两个想法是使用一个单词=>出现次数的散列,或者使用一个末端节点出现次数的trie。我有足够的内存用于哈希数组,但我认为trie的查找速度会一样快或更快 什么方法最好?我会使用Dictionary对象,其中关

(就目前而言,这在本质上是相当假设的,因此我没有太多细节要提供。)

我有一个随机(英语)单词的平面文件,每行一个。我需要编写一个高效的程序来计算每个单词出现的次数。这个文件很大(可能是1GB左右),但我有足够的内存。它们存储在永久介质上,所以读取速度很慢,所以我只需要线性地读取一次

我脑子里的两个想法是使用一个单词=>出现次数的散列,或者使用一个末端节点出现次数的trie。我有足够的内存用于哈希数组,但我认为trie的查找速度会一样快或更快


什么方法最好?

我会使用Dictionary对象,其中关键字转换为小写,值为计数。如果字典不包含该单词,请将其值添加为1。如果确实包含单词,则增加值。

一个简单的python脚本:

import collections
f = file('words.txt')
counts = collections.defaultdict(int)
for line in f:
    counts[line.strip()] +=1

print "\n".join("%s: %d" % (word, count) for (word, count) in counts.iteritems())

我认为trie对于您的用例来说是过度的。我会使用单词=>#的哈希值。即使使用像Perl这样的慢速解释语言,您也可以在几分钟内以这种方式咀嚼1GB文件。(我以前做过这件事。)

我有足够的内存用于哈希数组,但我认为trie的查找速度会一样快或更快

此代码将运行多少次?如果你只做一次,我会说优化你的时间,而不是你的CPU的时间,只要做任何最快的实现(在合理的范围内)。如果您有一个实现键值接口的标准库函数,只需使用它即可


如果您多次这样做,那么获取数据文件的一个子集(或多个子集),并对您的选项进行基准测试。在不了解更多数据集的情况下,推荐一个数据集而不是另一个数据集是值得怀疑的。

鉴于阅读速度较慢,这可能不会产生任何明显的差异。无论如何,总的时间将完全由读取数据的时间决定,所以这是您应该努力优化的。对于内存中的算法(实际上主要是数据结构),只需使用您觉得最舒服的语言中最方便的方法即可。

哈希表(如果操作正确,并且您说您有很多RAM)O(1)来计算特定单词,而trie将是O(n),其中n是单词的长度


有了足够大的哈希空间,哈希表的性能会比trie好得多。

我认为计数为叶子的trie可能会更快

任何像样的哈希表实现都需要完全读取单词,使用哈希函数进行处理,最后在表中进行查找

可以实现trie,以便在阅读单词时进行搜索。这样,在建立了唯一的单词前缀之后,您通常会发现自己跳过了字符,而不是对单词进行完整的查找

例如,如果你读过“乌龟”这个字,提尔人就会知道,唯一可能以这种方式开头的单词就是乌龟

如果在一个单词上执行这种内联搜索的速度比哈希算法进行哈希运算的速度快,那么应该能够更快

然而,这完全是矫枉过正。既然你说这纯粹是假设性的,我想你会想要一个假设性的答案。使用在合理时间内执行任务的最易维护的解决方案。微优化通常会在工时上浪费比在CPU时间上节省更多的时间。

使用Python

在询问集合数据类型是否在哈希表中之前,逐行将这些元素添加到集合数据类型中。在您知道它在集合中之后,再添加字典值2,因为您之前已将其添加到集合中一次


这将减少每次询问字典时的一些内存和计算量,相反,将更好地处理唯一值的单词,在调用结束时,只需将字典中未包含的所有单词从集合中转储,值为1。(与集合相关的两个集合相交)

在很大程度上,这取决于捕获数据后要对其执行的操作。见

啊,对了。如果是python,使用哈希内置项将比trie快,因为它使用本机代码。@zzzeek:哈希表查找是O(1),获取单词的哈希摘要是O(n),其中n是单词的长度。您可以用
int
替换
lambda:0
(因为
int()
也将返回0)。KISS。无论哪种方式,对数据结构的访问都应该是相当透明的。根据散列算法的不同,散列也可以是O(n)。或者更好,或者更糟。一个好的哈希算法总是O(n),其中
n
是单词的长度,所以big-O的复杂度基本相同,只是发生在算法的不同部分。就像他们说的,你必须至少扫描线性单词来对其进行哈希运算,或者用它遍历trie,所以会有一个O(n)不管是哪种方式,我想得越多,我就越意识到哈希算法也是O(n)。然而,在现代处理器上,一个好的哈希算法一次可以处理64位的密钥,而trie一次可以处理一个或两个字节的密钥。字典不只是一个哈希表吗?顺便说一句,我没有使用.NET。