我正在为教育目的创建自己的哈希表实现。
增加哈希表大小的最佳方法是什么?
我目前是将哈希数组大小翻倍。
我使用的哈希函数是:key模arraysize。
使用这种方法的问题在于,如果键是2、4、6、8,那么数组大小会不断增加。
如何解决这个问题?是否有更好的增加哈希表大小的方法?改变我的哈希函数是否有所帮助?
注意:我的键都是整数!
我正在为教育目的创建自己的哈希表实现。
增加哈希表大小的最佳方法是什么?
我目前是将哈希数组大小翻倍。
我使用的哈希函数是:key模arraysize。
使用这种方法的问题在于,如果键是2、4、6、8,那么数组大小会不断增加。
如何解决这个问题?是否有更好的增加哈希表大小的方法?改变我的哈希函数是否有所帮助?
注意:我的键都是整数!
哈希表通常通过确保哈希表的大小是质数来避免此问题。当你重新调整表格大小时,将其加倍,然后向上取整到比加倍后的第一个质数更大的质数。这样做可以避免类似于你所描述的聚集问题。
现在,找到下一个质数确实需要一点时间,但并不多。与重新哈希哈希表内容所涉及的时间相比,找到下一个质数几乎不需要时间。有关说明,请参见《优化错误的事情》。
/**
* Applies a supplemental hash function to a given hashCode, which defends against poor quality hash functions.
* This is critical because HashMap uses power-of-two length hash tables, that otherwise encounter collisions
* for hashCodes that do not differ in lower bits. Note: Null keys always map to hash 0, thus index 0.
*/
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
mod
作为哈希函数的话,选择一个质数作为哈希表的大小。Quadratic Probing
在冲突时查找最终位置。对于第 i
次冲突,公式为 h(x,i) = (Hash(x) + i*i) mod TableSize
。Quadratic Probing
实现://find a position to set the key
int findPos( int key, YourHashTable h )
{
int curPos;
int collisionNum = 0;
curPos = key % h.TableSize;
//while find a collision
while( h[curPos] != null && h[curPos] != key )
{
//f(i) = i*i = f(i-1) + 2*i -1
curPos += 2 * ++collisionNum - 1;
//do the mod only use - for efficiency
if( curPos >= h.TableSize )
curPos -= h.TableSize;
}
return curPos;
}
index = hashValue & (array.length-1)
(当array.length
是2的幂时等同于模运算)。loadFactor * array.length
时,数组的长度将加倍。