哈希表及处理冲突的方法

来源:互联网 发布:成都app软件开发 编辑:程序博客网 时间:2024/06/04 18:35

哈希法又称散列法、杂凑法以及关键字地址计算法等,相应的表称为哈希表。这种方法的基本思想是:首先在元素的关键字k和元素的存储位置p之间建立一个对应关系f,使得p=f(k)f称为哈希函数。创建哈希表时,把关键字为k的元素直接存入地址为f(k)的单元;以后当查找关键字为k的元素时,再利用哈希函数计算出该元素的存储位置p=f(k),从而达到按关键字直接存取元素的目的。

   当关键字集合很大时,关键字值不同的元素可能会映象到哈希表的同一地址上,即 k1k2 ,但 Hk1=Hk2),这种现象称为冲突,此时称k1k2同义词。实际中,冲突是不可避免的,只能通过改进哈希函数的性能来减少冲突。

综上所述,哈希法主要包括以下两方面的内容:

 1)如何构造哈希函数

 2)如何处理冲突。

8.4.1   哈希函数的构造方法

    构造哈希函数的原则是:函数本身便于计算;计算出来的地址分布均匀,即对任一关键字kf(k) 对应不同地址的概率相等,目的是尽可能减少冲突。

下面介绍构造哈希函数常用的五种方法。

1 数字分析法

      如果事先知道关键字集合,并且每个关键字的位数比哈希表的地址码位数多时,可以从关键字中选出分布较均匀的若干位,构成哈希地址。例如,有80个记录,关键字为8位十进制整数d1d2d3…d7d8,如哈希表长取100,则哈希表的地址空间为:00~99。假设经过分析,各关键字中 d4d7的取值分布较均匀,则哈希函数为:h(key)=h(d1d2d3…d7d8)=d4d7。例如,h(81346532)=43h(81301367)=06。相反,假设经过分析,各关键字中 d1d8的取值分布极不均匀, d都等于5d都等于2,此时,如果哈希函数为:h(key)=h(d1d2d3…d7d8)=d1d8,则所有关键字的地址码都是52,显然不可取。

2 平方取中法

当无法确定关键字中哪几位分布较均匀时,可以先求出关键字的平方值,然后按需要取平方值的中间几位作为哈希地址。这是因为:平方后中间几位和关键字中每一位都相关,故不同关键字会以较高的概率产生不同的哈希地址。

例:我们把英文字母在字母表中的位置序号作为该英文字母的内部编码。例如K的内部编码为11E的内部编码为05Y的内部编码为25A的内部编码为01, B的内部编码为02。由此组成关键字“KEYA”的内部代码为11052501,同理我们可以得到关键字“KYAB”、“AKEY”、“BKEY”的内部编码。之后对关键字进行平方运算后,取出第7到第9位作为该关键字哈希地址,如图8.23所示。

 

 

关键字

内部编码

内部编码的平方值

H(k)关键字的哈希地址

KEYA

11050201

122157778355001

778

KYAB

11250102

126564795010404

795

AKEY

01110525

001233265775625

265

BKEY

02110525

004454315775625

315

8.23平方取中法求得的哈希地址

3 分段叠加法

      这种方法是按哈希表地址位数将关键字分成位数相等的几部分(最后一部分可以较短),然后将这几部分相加,舍弃最高进位后的结果就是该关键字的哈希地址。具体方法有折叠法移位法。移位法是将分割后的每部分低位对齐相加,折叠法是从一端向另一端沿分割界来回折叠(奇数段为正序,偶数段为倒序),然后将各段相加。例如:key=12360324711202065,哈希表长度为1000,则应把关键字分成3位一段,在此舍去最低的两位65,分别进行移位叠加和折叠叠加,求得哈希地址为105907,如图8.24所示。

 

 

  2   3                    1   2   3

  0   3                    3   0   6

  4   7                    2   4   7

  1   2                    2   1   1

+   0   2   0               +  0   2   0

        ————————            —————————

        1   1   0   5                    9   0   7

 

a)移位叠加                    (b) 折叠叠加

 

                      8.24 由叠加法求哈希地址

 

4 除留余数法

假设哈希表长为mp为小于等于m的最大素数,则哈希函数为

hk=k  %  p ,其中%为模p取余运算。

例如,已知待散列元素为(18756043549046),表长m=10p=7,则有

    h(18)=18 % 7=4    h(75)=75 % 7=5    h(60)=60 % 7=4   

    h(43)=43 % 7=1    h(54)=54 % 7=5    h(90)=90 % 7=6   

    h(46)=46 % 7=4

此时冲突较多。为减少冲突,可取较大的m值和p值,如m=p=13,结果如下:

    h(18)=18 % 13=5    h(75)=75 % 13=10    h(60)=60 % 13=8    

    h(43)=43 % 13=4    h(54)=54 % 13=2    h(90)=90 % 13=12   

    h(46)=46 % 13=7

此时没有冲突,如图8.25所示。

 

     1      2     3     4     5      6     7     8     9     10     11    12

 

 

 

54

 

43

18

 

46

60

 

75

 

90

                      8.25  除留余数法求哈希地址

 

5 伪随机数法

    采用一个伪随机函数做哈希函数,即h(key)=random(key)

在实际应用中,应根据具体情况,灵活采用不同的方法,并用实际数据测试它的性能,以便做出正确判定。通常应考虑以下五个因素 

l         计算哈希函数所需时间 (简单)。

l         关键字的长度。

l         哈希表大小。

l         关键字分布情况。

l         记录查找频率

8.4.2   处理冲突的方法

   通过构造性能良好的哈希函数,可以减少冲突,但一般不可能完全避免冲突,因此解决冲突是哈希法的另一个关键问题。创建哈希表和查找哈希表都会遇到冲突,两种情况下解决冲突的方法应该一致。下面以创建哈希表为例,说明解决冲突的方法。常用的解决冲突方法有以下四种:

1.         开放定址法

这种方法也称再散列法其基本思想是:当关键字key的哈希地址p=Hkey)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,直到找出一个不冲突的哈希地址pi 将相应元素存入其中。这种方法有一个通用的再散列函数形式:

          Hi=Hkey+di% m   i=12…,n

    其中Hkey)为哈希函数,为表长,di称为增量序列。增量序列的取值方式不同,相应的再散列方式也不同。主要有以下三种:

l         线性探测再散列

    dii=123m-1

这种方法的特点是:冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。

l         二次探测再散列

    di=12-1222-22k2-k2    ( k<=m/2 )

    这种方法的特点是:冲突发生时,在表的左右进行跳跃式探测,比较灵活。

l         伪随机探测再散列

    di=伪随机数序列。

具体实现时,应建立一个伪随机数发生器,(如i=(i+p) % m),并给定一个随机数做起点。

例如,已知哈希表长度m=11,哈希函数为:Hkey= key  %  11,则H47=3H26=4H60=5,假设下一个关键字为69,则H69=3,与47冲突。如果用线性探测再散列处理冲突,下一个哈希地址为H1=3 + 1% 11 = 4,仍然冲突,再找下一个哈希地址为H2=3 + 2% 11 = 5,还是冲突,继续找下一个哈希地址为H3=3 + 3% 11 = 6,此时不再冲突,将69填入5号单元,参图8.26 (a)。如果用二次探测再散列处理冲突,下一个哈希地址为H1=3 + 12% 11 = 4,仍然冲突,再找下一个哈希地址为H2=3 - 12% 11 = 2,此时不再冲突,将69填入2号单元,参图8.26 (b)。如果用伪随机探测再散列处理冲突,且伪随机数序列为:259……..,则下一个哈希地址为H1=3 + 2% 11 = 5,仍然冲突,再找下一个哈希地址为H2=3 + 5% 11 = 8,此时不再冲突,将69填入8号单元,参图8.26 (c)

 

 

                                                       10    

 

 

 

 

47

26

60

69

 

 

 

 

         a 用线性探测再散列处理冲突

 

 

                                                       10    

 

 

 

69

47

26

60

 

 

 

 

 

         b 用二次探测再散列处理冲突

 

 

                                                       10    

 

 

 

 

47

26

60

 

 

69

 

 

         c 用伪随机探测再散列处理冲突

 

                      8.26开放地址法处理冲突

从上述例子可以看出,线性探测再散列容易产生“二次聚集”,即在处理同义词的冲突时又导致非同义词的冲突。例如,当表中i, i+1 ,i+2三个单元已满时,下一个哈希地址为i, i+1 ,i+2,或i+3的元素,都将填入i+3这同一个单元,而这四个元素并非同义词。线性探测再散列的优点是:只要哈希表不满,就一定能找到一个不冲突的哈希地址,而二次探测再散列和伪随机探测再散列则不一定。

2.         再哈希法

    这种方法是同时构造多个不同的哈希函数:

    Hi=RH1key  i=12k

当哈希地址Hi=RH1key)发生冲突时,再计算Hi=RH2key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。

3.         链地址法

    这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。

例如,已知一组关键字(324036531646712742244964),哈希表长度为13,哈希函数为:Hkey= key % 13,则用链地址法处理冲突的结果如图8.27所示:

 

  哈希表及处理冲突的方法(转) - 另一片天空 - 仰望天空 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


8.27  链地址法处理冲突时的哈希表

 

本例的平均查找长度 ASL=(1*7+2*4+3*1)=1.5

 

4建立公共溢出区

这种方法的基本思想是:将哈希表分为基本表溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表

0 2
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 支付宝的聊天记录被删了怎么办 彩票站买彩票把钱付了没出票怎么办 与异性朋友聊天没话题了怎么办 快递写错地址但已经发货了怎么办 快递写错电话但已经发货了怎么办 微信添加好友功能被限制怎么办 qq号被冻结了限制解封怎么办 被别人强制拉入qq群怎么办 qq群里的图片过期了怎么办 q附近人不能关注不能发信息怎么办 qq畅聊之火掉了怎么办 打印机打印时上面空白留太多怎么办 发短信一直空格里面写0怎么办 网贷获取我新手机号通讯录怎么办 系统音频驱动异常或未安装怎么办 附近功能已屏蔽你的qq好友怎么办 新申请的qq号忘了怎么办 刚申请的qq号忘了怎么办 以前申请的qq号忘了怎么办 小孩玩手机游戏扣费了怎么办 手机qq好友头像显示不出来怎么办 qq的一些重要数据被清理怎么办 华为p9微信听筒声音小怎么办 win10我的电脑图标没了怎么办 小米5x里的微信头像不清楚怎么办 微信头像换了总是模糊怎么办 找到老公暧昧对象的微信怎么办 朋友欠我钱一直拖找借口怎么办 陌陌附近的人不按距离排序怎么办 老婆一直要管我的钱怎么办 老公不肯把钱交给老婆管怎么办 愿意和做朋友不愿意做情侣怎么办 欠信用卡碰到第三方不愿协调怎么办 qq密码忘记了申诉不回来怎么办 当你老公烦你了你该怎么办 自己有漂亮媳妇还经常想去嫖怎么办 微信号封了找不到好友解封怎么办 别人总是提起你的黑历史怎么办 换了手机微信登录不上怎么办 qq不小心清空了聊天记录怎么办 人家介绍了外地媳妇跑了怎么办