散列——再散列与双散列(C++)

双散列:

    原理很朴素。既然第一个哈希值会发生冲突,那再来一个哈希值不就好了?

    比如,现在有两个哈希函数,分别记作Hash1(X)与Hash2(X),其中,X为关键字。

    假如现在我们得到的第一个哈希值Hash1所对应的位置已经有先来的人了,位子已经被占了,那这个X肯定没办法放进去了;那么,便再计算这个X的Hash2,发现第二个位子还是空的,于是我们把Hash2放进去。这就是原理,但论谁都应该会有一些疑问,写在下面。

对双散列的思考:

    很明显,这种策略并不能从根本上解决问题,甚至也都没办法从基础上解决问题。因为表仍然是那一张,只不过每个关键字现在能够拥有两个哈希值了,但这对每一个关键字来说都是一样的。或许一个好的哈希函数能够在这种情况下尽可能的填补缺陷(比方说,第一个哈希函数算出来的值大多数占据了表的一半,而另外一个哈希函数则占据另外一半,那这种对半开的函数就非常棒了。当然,这只是一种愿望,实际中不一定真的存在这种巧合),但情况仍然相对糟糕。

    那比方说三散列呢?四散列?看起来好像都是可行的策略,但要设计出这种方案着实困难。对于哈希函数的设计既复杂也浪费,而且往往还不能得到期望的结果。

    当然,实际情况其实也并没有那么糟糕。放到实际情况中去考量的话,这种策略预期的探测次数几乎和随机冲突解决方法的情形是相同的。

    吸引人吗?是的,吸引人。但我也不是很懂就是了。

再散列:

    同样不难,比起下一个可扩散列来讲,这要随和的多了。

    原理也很简单。当表不够大了,就把表扩大一倍不就行了(这个一倍也是有原因的,具体情况适当了解即可)?

代码:

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;
}

    很好理解的,书上给的代码相当易懂,就不解释了。

猜你喜欢

转载自blog.csdn.net/Tokameine/article/details/113791329