我的哈希表的当前实现是使用线性探测,现在我想转移到二次探测(然后可能再转到链式哈希和双重哈希)。我已经阅读了一些文章、教程、维基百科等等……但我仍然不知道该做什么。
基本上,线性探测有一个步长为1,因此很容易实现。当从哈希表中查找、插入或删除元素时,我需要计算哈希值,方法如下:
关于二次探测法,我认为需要做的是改变“索引”步长如何计算,但我不知道该如何做。我看过各种代码片段,它们都有些不同。
此外,我看过一些实现二次探测法的代码,其中哈希函数被更改以适应这一点(但并非全部)。这个改变真的必要吗?还是我可以避免修改哈希函数并仍然使用二次探测法?
编辑:在阅读Eli Bendersky指出的所有内容后,我想我已经有了大致的思路。以下是http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_hashtable.aspx上的一部分代码:
如果有什么需要,我会做以下事情:
基本上,线性探测有一个步长为1,因此很容易实现。当从哈希表中查找、插入或删除元素时,我需要计算哈希值,方法如下:
index = hash_function(key) % table_size;
然后,在搜索、插入或删除时,我会循环遍历表格,直到找到一个空闲的桶,就像这样:
do {
if(/* CHECK IF IT'S THE ELEMENT WE WANT */) {
// FOUND ELEMENT
return;
} else {
index = (index + 1) % table_size;
}
while(/* LOOP UNTIL IT'S NECESSARY */);
关于二次探测法,我认为需要做的是改变“索引”步长如何计算,但我不知道该如何做。我看过各种代码片段,它们都有些不同。
此外,我看过一些实现二次探测法的代码,其中哈希函数被更改以适应这一点(但并非全部)。这个改变真的必要吗?还是我可以避免修改哈希函数并仍然使用二次探测法?
编辑:在阅读Eli Bendersky指出的所有内容后,我想我已经有了大致的思路。以下是http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_hashtable.aspx上的一部分代码:
15 for ( step = 1; table->table[h] != EMPTY; step++ ) {
16 if ( compare ( key, table->table[h] ) == 0 )
17 return 1;
18
19 /* Move forward by quadratically, wrap if necessary */
20 h = ( h + ( step * step - step ) / 2 ) % table->size;
21 }
有两件事我不明白...他们说二次探测通常使用 c(i)=i^2
。然而,在上面的代码中,它做的更像是 c(i)=(i^2-i)/2
我准备在我的代码中实现这个算法,但我只会简单地做:
index = (index + (index^index)) % table_size;
……而不是:
index = (index + (index^index - index)/2) % table_size;
如果有什么需要,我会做以下事情:
index = (index + (index^index)/2) % table_size;
因为我看到其他代码示例将其除以2。但是我不明白为什么...
1) 为什么要减去这个步骤?
2) 为什么要将其除以2?