我对设置散列数组的良好且有效的大小感到困惑。我正在阅读的这本书说,负载系数应该在75%左右才能成为一个好的散列阵列。但在实际尝试测试散列数组放置键之前,我不知道如何在理论上决定数组的大小。达到最佳散列阵列大小是否有任何线索或重要提示?并且大小取决于您用于散列的方法吗?
答案 0 :(得分:1)
您的哈希表解决方案不依赖于事先知道要放入表中的元素数量。相反,动态增长和萎缩是最好的。
建议使用小的哈希表大小(< = 1)进行初始化,并在加载因子达到150-200%时将哈希表大小翻两番。这涉及将整个旧表重新散列为一个新表,但在现实生活中不应经常发生。
还应该有缩小阈值,大约是增长阈值的1/2。
通过使增长和缩小阈值彼此远离,如果您在临界大小周围添加/删除哈希表元素,则会阻止大量工作。
哈希表大小有一个额外的好处是它们是素数。典型的散列函数包含一些预哈希函数,比如说unsigned Hash(unsigned item)
然后使用哈希表大小修改结果:BucketIndex = Hash(item)%HashTableSize
如果Hash()
不做,则主要哈希表大小会改善分散很好。
对于素数值,我建议在Hash数据结构中保留HashPrime_Index,然后在需要知道哈希表的大小时使用下表。
static const size_t HashPrime[] = { 0, 2, 3, 7, 13, 31, 61, ... }; // Primes just less than powers of 2.
成长时,使用0,3,13 ......当收缩时使用......,61,13,2。
当您使用主哈希表大小时,最佳哈希表大小更少取决于方法Hash()
。注意:Hash()应返回一个大整数。
答案 1 :(得分:0)
随着元素数量的增长,您可以重新散列哈希表。此过程会更改存储桶的数量。根据细节,这甚至可能是必要。
如果你使用链接(即具有相同散列值的所有元素都进入同一个桶),那么理论上你可以无限制地增长表而不需要重新散列,但它最终基本上只是一个链表(或任何序列)容器代表一个桶)。因此,您应该跟踪当前的负载因子(元素数量除以桶数),并在表格过大时增大表格。
如果你使用探测(“开放寻址”),那么一旦探测无法为新元素找到一个空闲点,你就重新进行。