哈希函數把一個無窮大的輸入集合映射到一個有限大小的輸出集合。不同的關鍵字可能會被映射到同一個數組下標,如此一來就導致了哈希衝突。哈希表必須實現解決衝突的方法。
我們的哈希表將使用開放地址法和再散列法。在桶索引衝突後,再散列法會使用兩個哈希函數來計算鍵值對將要保存的桶索引值。
有關其他哈希衝突的解決方法,請查看附錄。
再散列法
索引i
衝突後應該使用的新的索引位置根據下面的函數給出:
index = hash_a(string) + i * hash_b(string) % num_buckets
我們看到,如果沒有哈希衝突的發生,i=0。此時,桶索引是字符串的hash_a
值。如果發生了衝突,索引將由hash_b
進行調整。
有種可能是,hash_b
返回了0,導致i*hash_b(string)%num_buckets
也返回了0。這會使得哈希表不停的向同一個桶中插入鍵值對。我們可以通過對第二個哈希的結果加一來避免這種情況,以確保第二個項的結果不會是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;
}
上一篇:教你從零開始寫一個哈希表–哈希函數
下一篇:教你從零開始寫一個哈希表–接口