上一章我們解釋了Hash table
中最重要的hash函數
,並用僞代碼和C語言實現了一個我們自己的hash函數
,hash函數
中碰撞
是無法避免的,當發生碰撞
時我們改如何有效的處理呢?這章我們就來講解下。
處理碰撞
hash函數
中將無限大的輸入映射到有限的輸出中,當不同的輸入映射到相同的輸出時,就會發生碰撞
,每個的hash表
都會採用不同的方法來處理碰撞
。
我們的哈希表將使用一種稱爲開放地址的雙重哈希的技術來處理衝突。雙重哈希使用兩個散列函數來計算在發生碰撞
後存儲記錄的索引。
雙重哈希
當i
發生碰撞
後我們使用如下方式來獲取索引:
index = hash_a(string) + i * hash_b(string) % num_buckets
當沒有發生碰撞
時,i=0
,所以索引就是hash_a
的值,發生碰撞
後,hash_a
的結果就需要經過一次hash_b
的處理。
hash_b
可能會返回0
,將第二項減少到0
,這就導致hash表
會將多個記錄插入到同一個bucket
中,我們可以在hash_b
的結果後加1
來處理這種情況,確保它永遠不會爲0
:
index = (hash_a(string) + i * (hash_b(string) + 1)) % num_buckets
算法實現
// hash_table.c
static int ht_get_hash(const char* s, const int num_buckets, const int attempt) {
const int hash_a = ht_hash(s, HT_PRIME_1, num_buckets);
const int hash_b = ht_hash(s, HT_PRIME_2, num_buckets);
return (hash_a + (attempt * (hash_b + 1))) % num_buckets;
}
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。