哈希表及处理冲突的方法
http://www.360doc.com/content/14/0721/09/16319846_395862328.shtml
哈希法又称 散列法、杂凑法以及关键字地址计算法 等,相应的表称为 哈希表。 这种方法的基本思想是: 首先在元素的关键字 k 和元素的存储位置 p 之间建立一个对应关系 f ,使得 p=f(k) , f 称为哈希函数 。创建哈希表时,把关键字为 k 的元素 直接存入地址为 f(k) 的单元;以后当查找关键字为 k 的元素时,再利用哈希函数计算出该元素的存储位置 p=f(k) ,从而达到按关键 字直接存取元素的目的。
当关键字集合很大时,关键字值不同的元素可能会映象到哈希表的同一地址上 ,即 k1 ≠ k2 ,但 H ( k1 ) =H ( k2 ),这种现象称为冲突,此时称 k1 和 k2 为同义词。实际中,冲突是不可避免的,只能通过改进哈希函数的性能来减少冲突。
综上所述,哈希法主要包括以下两方面的内容:
1 )如何构造哈希函数
2 )如何处理冲突。
8.4.1 哈希函数的构造方法
构造哈希函数的原则是: ① 函数本身便于计算; ② 计算出来的地址分布均匀,即对任一关键字 k , f(k) 对应不同地址的概率相等,目的是尽可能减少冲突。
下面介绍构造哈希函数常用的五种方法。
1 . 数字分析法
如果事先知道关键字集合,并且每个关键字的位数比哈希表的地址码位数多时,可以从关键字中选出分布较均匀的若干位,构成哈希地址。
2 . 平方取中法
当无法确定关键字中哪几位分布较均匀时,可以先求出关键字的平方值,然后按需要取平方值的中间几位作为哈希地址。这是因为:平方后中间几位和关键字中每一位都相关,故不同关键字会以较高的概率产生不同的哈希地址。
3 . 分段叠加法
这种方法是按哈希表地址位数将关键字分成位数相等的几部分(最后一部分可以较短),然后将这几部分相加,舍弃最高进位后的结果就是该关键字的哈希地址。具体方法有折叠法与移位法。移位法是将分割后的每部分低位对齐相加,折叠法是从一端向另一端沿分割界来回折叠(奇数段为正序,偶数段为倒序),然后将各段相加。
4 . 除留余数法
假设哈希表长为 m , p 为小于等于 m 的最大素数,则哈希函数为
h ( k ) =k % p ,其中 % 为模 p 取余运算。
5 . 伪随机数法
采用一个伪随机函数做哈希函数,即 h(key)=random(key) 。
在实际应用中,应根据具体情况,灵活采用不同的方法,并用实际数据测试它的性能,以便做出正确判定。通常应考虑以下五个因素 :
l 计算哈希函数所需时间 (简单)。
l 关键字的长度。
l 哈希表大小。
l 关键字分布情况。
l 记录查找频率
8.4.2 处理冲突的 方法
通过构造性能良好的哈希函数,可以减少冲突,但一般不可能完全避免冲突,因此解决冲突是哈希法的另一个关键问题。创建哈希表和查找哈希表都会遇到冲突,两种情况下解决冲突的方法应该一致。下面以创建哈希表为例,说明解决冲突的方法。常用的解决冲突方法有以下四种:
1. 开放定址法
这种方法也称 再散列法 , 其基本思想是:当关键字 key 的哈希地址 p=H ( key )出现冲突时,以 p 为基础,产生另一个哈希地址 p1 ,如果 p1 仍然冲突,再以 p 为基础,产生另一个哈希地址 p2 , … ,直到找出一个不冲突的哈希地址 pi , 将相应元素存入其中。
2. 再哈希法
这种方法是同时构造多个不同的哈希函数:
H i =RH 1 ( key ) i=1 , 2 , … , k
当哈希地址 H i =RH 1 ( key )发生冲突时,再计算 H i =RH 2 ( key )……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。
3. 链地址法
这种方法的基本思想是将所有哈希地址为 i 的元素构成一个称为同义词链的单链表 ,并将单链表的头指针存在哈希表的第 i 个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。
4. 建立公共溢出区
这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表