排序和搜索(三)——hash查找之冲突解决(2)

在http://blog.csdn.net/brave_jcc/article/details/79499336中提到了几种hash函数,但是也只是最大可能减少冲突,并未真正解决冲突问题,本文主要介绍几种常见的冲突解决方法

(1)开放寻址+线性探测

在遇到冲突的时候,尝试查找另一个空槽用以保存导致冲突的数据值。一个简单的方法是从原始哈希值位置开始,然后以顺序方式移动槽,直到遇到第一个空槽。注意,我们可能需要回到第一个槽(循环)以查找整个散列表。这种冲突解决过程被称为开放寻址,因为它试图在散列表中找到下一个空槽或地址。通过系统地一次访问每个槽,我们执行称为线性探测的开放寻址技术。

查找:使用开放寻址和线性探测建立哈希表,就必须使用同样的方法查找hash表。如果我们在大小为10的哈希表中查找数据61,根据余数法求得槽位置为1,而位置1处存的值可能是31,由于有这种冲突解决方法,这时候不必着急返回False,而是顺着槽1逐个查找,直至回到位置1还没找到,方可返回False

缺点:数据在表中聚集。这意味着如果在相同的散列值处发生很多冲突,则将通过线性探测来填充多个周边槽。这将影响正在插入的其他数据

聚集解决方案:扩展线性探测技术,使得不是顺序地查找下一个开放槽,而是跳过槽,从而更均匀地分布已经引起冲突的项。这将潜在地减少发生的聚集。例如加3,在存储数据31后,再存储61,遇到冲突,不是紧挨着位置1查找空余槽,而是查看位置11后的第3个槽是否空余

在冲突后寻找另一个槽的过程叫 重新散列。使用简单的线性探测,rehash 函数是 newhashvalue = rehash(oldhashvalue)其中 rehash(pos)=(pos + 1)%sizeoftable。 加3rehash 可以定义为rehash(pos)=(pos + 3)%sizeoftable。一般来说,rehash(pos)=(pos + skip)%sizeoftable。重要的是要注意,“跳过”的大小必须使得表中的所有槽最终都被访问。否则,表的一部分将不被使用。

(2)二次探测

在(1)中为了避面解决冲突过程中遇到的聚集现象,我们使用常亮跳过。二次探测中,采用散列值递增1,3,5,7,9.例如第一个数据的散列值为h,则连续值是h + 1,h + 4,h + 9,h + 16,等等。

(3)链接

多个数据对应hash表中相同的槽,冲突。链接方法是保存对这些数据的引用,随着越来越多的项哈希到相同的位置,搜索集合中的项的难度增加。



猜你喜欢

转载自blog.csdn.net/brave_jcc/article/details/79505523