解决哈希冲突两种常见的方法是:闭散列和开散列
一、闭散列
闭散列法又称开放地址法,当发生哈希冲突时,如果哈希表未满,说明其中必然还有空位置,可以把 key 存放到表中 “下一个” 空位置中去,那如何寻找 “下一个” 空位置?
1、线性探测
从发生冲突的位置开始,依次继续向后探测,直到找到空位置为止
int a[ ] = {37, 25, 14, 36, 49, 68, 57, 11, 19};
int HashFunc(int key)
{
return key % 19;
}

2、二次探测
Hi = (H0 ± i^2) % 哈希表长度,其中,H0 = HashFunc(key),i = 1, 2, …
int a[ ] = {37, 25, 14, 36, 49, 68, 57, 11, 19};
int HashFunc(int key)
{
return key % 19;
}

3、双重哈希
Hi = (H0 + i * H1) % 哈希表长度,其中,H0 = HashFunc1(key),H1 = HashFunc2(key),i = 1, 2, …
注意
删除操作
二、开散列
开散列法又称链地址法(开链法),将具有相同哈希地址的关键码使用链表等数据结构进行存储
int a[ ] = {37, 25, 14, 36, 49, 68, 57, 11, 19};
int HashFunc(int key)
{
return key % 17;
}

使用哈希函数计算出每个元素所在的桶号,同一个桶的链表中存放哈希冲突的元素,各链表的头结点存储在哈希表中
三、负载因子 α
α = 哈希表中元素个数 / 哈希表长度
注意
负载因子对闭散列尤为重要,应严格限制在 0.7 ~ 0.8 以下(超过 0.8,查找时 CPU 缓存不命中次数呈指数级上升),当然对于开散列,负载因子也不应过大,避免桶过深
// 使用素数表对齐做哈希表的容量,降低哈希冲突
const int _PrimeSize = 28;
static const unsigned long _PrimeList[_PrimeSize] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};
941

被折叠的 条评论
为什么被折叠?



