双散列:
原理很朴素。既然第一个哈希值会发生冲突,那再来一个哈希值不就好了?
比如,现在有两个哈希函数,分别记作Hash1(X)与Hash2(X),其中,X为关键字。
假如现在我们得到的第一个哈希值Hash1所对应的位置已经有先来的人了,位子已经被占了,那这个X肯定没办法放进去了;那么,便再计算这个X的Hash2,发现第二个位子还是空的,于是我们把Hash2放进去。这就是原理,但论谁都应该会有一些疑问,写在下面。
对双散列的思考:
很明显,这种策略并不能从根本上解决问题,甚至也都没办法从基础上解决问题。因为表仍然是那一张,只不过每个关键字现在能够拥有两个哈希值了,但这对每一个关键字来说都是一样的。或许一个好的哈希函数能够在这种情况下尽可能的填补缺陷(比方说,第一个哈希函数算出来的值大多数占据了表的一半,而另外一个哈希函数则占据另外一半,那这种对半开的函数就非常棒了。当然,这只是一种愿望,实际中不一定真的存在这种巧合),但情况仍然相对糟糕。
那比方说三散列呢?四散列?看起来好像都是可行的策略,但要设计出这种方案着实困难。对于哈希函数的设计既复杂也浪费,而且往往还不能得到期望的结果。
当然,实际情况其实也并没有那么糟糕。放到实际情况中去考量的话,这种策略预期的探测次数几乎和随机冲突解决方法的情形是相同的。
吸引人吗?是的,吸引人。但我也不是很懂就是了。
再散列:
扫描二维码关注公众号,回复:
12720906 查看本文章
同样不难,比起下一个可扩散列来讲,这要随和的多了。
原理也很简单。当表不够大了,就把表扩大一倍不就行了(这个一倍也是有原因的,具体情况适当了解即可)?
代码:
HashTable ReHash(HashTable H)
{
int OldSize;
OldSize = H->TableSize;
Cell* OldCells;
OldCells = H->TheCells;
H = InitializeTable(2 * OldSize);
for (int i = 0; i < OldSize; i++)
{
if (OldCells[i].Info == Legitimate)
Insert(OldCells[i].Key, H);
}
delete[] OldCells;
return H;
}
很好理解的,书上给的代码相当易懂,就不解释了。