我目前的散列表實現是使用線性探測,現在我想要移動到二次探測(後來鏈接,也許雙哈希)。我讀過一些文章,教程,維基百科等......但我仍然不知道我應該做什麼。從線性探測移動到二次探測(散列碰撞)
線性探測,基本上,有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 */);
至於二次探測,我想我需要做的是改變「指數」步長是如何計算的,但是這就是我不明白我應該怎麼做。我已經看過各種代碼,並且它們都有些不同。
此外,我已經看到一些二次探測的實現,其中散列函數被改變以適應(但不是全部)。這種改變是否真的需要,或者我可以避免修改哈希函數,並仍然使用二次探測?
編輯: 看完一切所指出的禮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;
...因爲我見過的其它代碼示例跳水兩次。雖然我不明白爲什麼...
1)爲什麼它會減去這個步驟?
2)爲什麼潛水2?
記住,二次探測纔有效,如果表大小是素數,負載因子是<0.5;請參閱http://eternallyconfuzzled.com/tuts/datastructures/jsw_tut_hashtable.aspx,瞭解有關不同衝突解決策略的概述。 – Christoph 2010-02-27 17:13:23
@Cristoph:該陳述並不完全正確。如果表格大小爲素數,那麼如果負載因數<0.5,則保證正常工作;但這不是真正的,這是二次探測工作的* only *情況。例如,它也可以用2次冪的表格大小和任意的加載因子有效(請參閱我的答案)。 – 2010-02-28 02:14:55
@Mathew:'工作'和'有效工作'之間有區別。如果負載因子太高,(次級)集羣可能會再次成爲問題 – Christoph 2010-03-02 09:38:09