上一章我们解释了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;
}
上一章:hash函数
下一章:完成Hash表API
原文地址:https://github.com/jamesroutley/write-a-hash-table/tree/master/05-methods