上周我正在学习哈希表,但我想知道为哈希表选择的最佳值是什么,以及哈希函数的表大小如何才能使其在良好的时间复杂度下运行。
这是我的哈希函数的代码:
h = 0
for i in range(len(key)):
h = (h * hashBase + ord(key[i])) % tableCapacity
return h
为什么选择hashBase = 1会增加哈希表操作的时间复杂度?为什么最好选择大桌子容量?另外,为什么呢。 hashBase = 250726和表容量= 250727会导致其操作变慢?
答案 0 :(得分:3)
tableCapacity
通常应与将散列到表中的键的数量保持合理的比率。确切的比例取决于如何处理哈希冲突-即:
个替代存储桶({"open addressing"又名“封闭式哈希” )):具有 good 哈希函数的存储桶比存储桶多20-50%键通常是合理的范围
每个存储桶都包含一些散列在其中的元素链("separate chaining"):使用 good 散列函数并不重要,因此您可以将一半像钥匙一样多的桶,或者两倍多的桶,事情会如虎添翼
也就是说,当散列函数不好,并且散列的密钥不够随机以帮助散列函数充分执行时,使用tableCapacity
可以减少冲突:尝试任何素数哈希值和上面列出的比率得出的值周围的数字。例如,如果您有6个键并正在使用单独的链接,则tableCapacity
为5、7或11会很合理。
但是,您的问题并未说明如何处理冲突,因此我们将其留给您。
让我们继续考虑哈希逻辑本身:
h = (h * hashBase + ord(key[i])) % tableCapacity
这就像this question中描述的“ MAD”哈希方法的简化/折衷形式一样-my answer中有一个解释,在此之后,我将假定您已经阅读了。
如果将您的功能与一般的MAD格式进行对比,我们会发现您在密钥的每个片段(字节?)上都使用% tableCapacity
。在python中可能有意义的原因是python没有像许多较低级语言(和CPU本身)一样溢出的固定位数的整数,因此如果您没有{{1} }在循环中进行}操作,%
的值可能会增大到与整个密钥相似的大小-如果您要生成视频文件的哈希值作为便宜的校验和,那将非常慢且浪费内存。因此,使用h
约束每次迭代后可以得到多大的%
是明智的,但是由于另一个答案中解释的原因,h
是质数,而{{1 }}应该选择通常产生比tableCapacity
大得多的值,以最大程度地减少较早的哈希桶比后来的哈希桶被更广泛地利用的数量(请参见上面链接的我的其他答案中的200/255示例)。>
总结:选择一个大的伪随机hashBase
-说一个32甚至64位的随机数,并给定打开/关闭-您选择的哈希设计。
为什么选择hashBase = 1会增加哈希表操作的时间复杂度?
tableCapacity
不应太小-这意味着hashBase
的贡献不太可能在应用tableCapacity
操作之前多次将hashBase
包裹在表周围再次,失去了分散映射所带来的所有好处。
为什么选择一个大桌子容量更好?
嗯,较大的表意味着更多的存储桶-相同数量的键将减少冲突,但是使用像样的哈希,您不必费力。更大的存储桶意味着更多的内存使用量和更少的缓存命中率,这会使事情变慢。
此外,为什么如此。 hashBase = 250726和表容量= 250727会导致其操作变慢?
如上所述,您希望hashBase大于表容量。