散列表(哈希表)——数据结构

一,散列表的基本概念

直接将元素的储存位置和其关键字之间建立某种直接关系,那么在进行查找时,就无需做比较或做很少次的比较,按照这种关系直接由关键字找到相应的记录,这就是散列表查找法的思想。

它通过对元素关键字值进行某种运算,直接求出元素的地址,即使用关键字到地址的直接转换方法,而不需要反复比较。因此散列查找法又称为杂凑法散列法

散列表中的术语:

  • 散列函数和散列地址:在记录的存储位置p和其关键字key之间建立一个确定的对应关系H,使得p=H(key),称这个对应关系H为散列函数,p为散列地址
  • 散列表:一个有限连续的地址空间,用以存储按散列函数计算得到相应散列地址的数据记录。通常散列表的存储空间是一个一维数组,散列地址是数组的下标。
  • 冲突和同义词对不同的关键字可能得到同一散列地址,即key1 != key2,但是H(key1) == H(key2),这种现象称为冲突。具有相同函数值的关键字对该散列表函数来说称为同义词,key1与key2互称为同义词。
  • eg:A称为关键字key,则A经过关系H后,在数组中的位置称为存储位置p;而不同的关键字8,4,经过关系(关键字%2)得到的存储地址都是0,称为冲突,而8,4则为同义词
  • 二,散列函数的构造方法

要求:

  • 函数计算要简单,每一关键字只能由一个散列地址与之对应
  • 函数的值域需在表长的范围内,计算出的散列地址的分布应均匀,尽可能减少冲突。

1,数字分析法

       适用情况:事先必须明确直到所有关键字每一位上各种数字的分布情况,然后找到随机的部分作为散列地址

       eg:一串数组   123685311   123193511  123387411  123338911  123346511  123824711   123395411

               如这串数字可知,前三个数字和后两个都一样,所以这五位就不不能作为散列地址,而中间四位近乎随机,所以可以将中间四位任意搭配作为散列地址。

2,平方取中法

        使用情况:不能事先了解关键字的所有情况,或难于直接从关键字中找到取值分散的几位

        因为在选定散列函数时不一定能知道关键字的全部情况,那么取关键字中的哪几位也不一定合适。所以将关键字平方后取中是一种比较常见的方法;

eg:关键字     内部编码          内部编码平方          取中做散列地址 

  • IDA1     09040101       081723426090201     426
  • IDB2     09040202       081725252200804     252
  • XID3     24090403       580347516702409     516
  • YID4     25090404       629528372883216     372

3,折叠法

           使用情况:适合于散列地址的位数较少,而关键字的位数较多,且难于直接从关键字中1找到取值较分散的几位

            eg:当散列表位数为1000,而关键字key=45387765213,则可以将关键字按3位一段分割得到:453 877 652 13。采用移位叠加:453+877+652+13=995,H(key)=995;边界叠加453+778+652+31=914,H(key)=914;即为两种方法的散列地址

(移位叠加是将分割后的每一部分的最低位对齐,然后相加;边界叠加是将两个相邻的部分沿边来回折叠,然后对齐相加)

4,除留余数法

这种方法计算简单,适用范围广,是最常见的构造散列函数的方法。它不仅可以对关键字直接取模,也可在折叠,平方取中等运算之后取模,这样能够保证散列地址一定落在散列表的地址空间中。

eg:假设散列表表长为m,选择一个不大于m的数p,用p去除关键字,除后所得余数为散列地址:H(key)=key%p。(这个方法的关键是选取适当的p,一般情况下,可以选取p为小于表长的最大质数。例如,表长为100,可以取p=97)

三,处理冲突的方法

1,开放寻址法

(1)开放寻址法

将散列表想成一个循环表,发生冲突时,从冲突的下一单元顺序寻找空单元,如果最后一个位置也没找到空单元,则回到表头开始继续查找,直到找到一个空位,就把此元素放入此空位中。如果找不到空位,则说明散列表已满,需要进行溢出处理

按照加一,加二,加三的顺序往后找(1,2,3,4,5,6,7,8........m-1)

(2)二次探测法

和线性探测法类似,但是按照另一种方法增加即(1*1,-1*1,2*2,-2*2,3*3,-3*3........k*k,-k*k(k<=m/2))

(3)伪随机探测法

 设d=伪随机序列,则散列地址=(H(key)+d)%m;

2,链地址法

把具有相同散列地址的记录放在同一个单链表中,称为同义词链表。

如果关键字AA,AAA,AAAA和A的散列地址相同,BB,BBB,BBBB和B的散列地址相同,则存储如下

算法分析

1,虽然散列表在关键字与记录的存储位置之间建立了直接映像,但由于冲突的发生,使得散列表的查找过程依然是一个给定值和关键字进行比较的过程。因此仍需以平均查找长度作为衡量散列表查找效率的量度。

2,查找过程中需和给定值进行比较的关键字个数取决于三个因素:散列函数,处理冲突的方法和填装因子。

填装因子a=表中填入的记录数/散列表的长度

a越小,发生冲突的可能性就越小,a越大,表中已经填入的记录越多,发生冲突的可能性就越大。

3,散列函数的“好坏”首先影响出现冲突的频繁程度。但一般情况下认为,凡是“均匀的”散列函数,对同一组随机数的关键字,产生冲突的可能性相同,假设所设定的散列函数是“均匀的”,则影响平均查找长度的因素只有两个——处理冲突的方法和填装因子a。

查找成功时平均查找长度=1/m*(第一层个数*1+第二层个数*2+第三层个数*3+.....);

查找失败时平均查找长度=1/m*(第一个同地址的数量+第二个相同地址的数量+......);

猜你喜欢

转载自blog.csdn.net/qq_46423166/article/details/106529459