哈希查找因使用哈希 (Hash) 函数而得名,哈希函数又叫散列函数,它是一种能把关键字映射成记录存贮地址的函数。
一.哈希表
①它是一种能把关键字映射成记录存贮地址的函数。
②假定数组 HT[0 ~ m-1] 为存贮记录的地址空间, m 为表长,哈希函数 H 以记录的关键字 K为自变量,计算出对应的函数值 H(K) ,并以它作为关键字 K 所标识的记录在表 HT 中的 ( 相对) 地址或索引号,这样产生的记录表 HT 叫做对应于哈希函数 H 的哈希表。
③简言之,在哈希表中,关键字为 K 的记录,存贮在 HT[H(K)] 位置。
④哈希函数值 H(K) 称为 K 的哈希地址或散列地址。
二.构造哈希表
构造哈希函数的方法很多,这里只介绍一些常用的,计算简便的方法。
1.平方取中法
算出关键字值的平方,再取其中若干位作为哈希函数值 ( 散列地址 ) 。
【例】假定表中各关键字是由字母组成的,用二位数字的整数 01 ~ 26 表示对应的 26 个英文字母在计算机中的内部编码,则使用平方取中法计算 KEYA , KEYB , AKEY , BKEY 的散列地址可得:
关键字 K
平方之后,取左起第 7 ~ 9 位作为散列地址。
2.除留余数法
【例】有一组关键字从 000001 到 859999 ,指定的存储区地址为 1000000 ~ 1005999 ,即 m= 6000 ,可选 P = 599 ,若要转换关键字 K = 172148 ,则有:
因 R 不在指定的地址范围内,所以,取哈希函数为:
故有:
这样就把关键字 K 直接转换成存储地址了。
三.可能产生的冲突:
(1)冲突
(2)安全避免冲突的条件
(3)冲突不可能完全避免
四.解决冲突的主要方法
虽然我们不希望发生冲突,但实际上发生冲突的可能性仍是存在的。当关键字值域远大于哈希表的长度,而且事先并不知道关键字的具体取值时。冲突就难免会发 生。另外,当关键字的实际取值大于哈希表的长度时,而且表中已装满了记录,如果插入一个新记录,不仅发生冲突,而且还会发生溢出。因此,处理冲突和溢出是 哈希技术中的两个重要问题。
1、开放定址法
(1)线性探查法(Linear Probing)
该方法的基本思想是:
探查过程终止于三种情况:
利用开放地址法的一般形式,线性探查法的探查序列为:
用线性探测法处理冲突,思路清晰,算法简单,但存在下列缺点:
① 处理溢出需另编程序。一般可另外设立一个溢出表,专门用来存放上述哈希表中放不下的记录。此溢出表最简单的结构是顺序表,查找方法可用顺序查找。
② 按上述算法建立起来的哈希表,删除工作非常困难。假如要从哈希表 HT 中删除一个记录,按理应将这个记录所在位置置为空,但我们不能这样做,而只能标上已被删除的标记,否则,将会影响以后的查找。
③ 线性探测法很容易产生堆聚现象。所谓堆聚现象,就是存入哈希表的记录在表中连成一片。按照线性探测法处理冲突,如果生成哈希地址的连续序列愈长 ( 即不同关键字值的哈希地址相邻在一起愈长 ) ,则当新的记录加入该表时,与这个序列发生冲突的可能性愈大。因此,哈希地址的较长连续序列比较短连续序列生长得快,这就意味着,一旦出现堆聚 ( 伴随着冲突 ) ,就将引起进一步的堆聚。
(2)线性补偿探测法
线性补偿探测法的基本思想是:
将线性探测的步长从 1 改为 Q ,即将上述算法中的 j = (j + 1) % m 改为: j = (j +Q) % m ,而且要求 Q 与 m 是互质的,以便能探测到哈希表中的所有单元。
【例】 PDP-11 小型计算机中的汇编程序所用的符合表,就采用此方法来解决冲突,所用表长 m= 1321 ,选用 Q = 25 。
(3)随机探测
随机探测的基本思想是:
将线性探测的步长从常数改为随机数,即令: j = (j + RN) % m ,其中 RN 是一个随机数。在实际程序中应预先用随机数发生器产生一个随机序列,将此序列作为依次探测的步长。这样就能使不同的关键字具有不同的探测次序,从而可以避免或减少堆聚。基于与线性探测法相同的理由,在线性补偿探测法和随机探测法中,删除一个记录后也要打上删除标记。
2、拉链法
(1)拉链法解决冲突的方法
与开放定址法相比,拉链法有如下几个优点:
①拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
②由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;
③开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间;
④在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。而对开放地址法构造的散列表,删除结点不能简单地将被删结点的空间置为空,否则将截断在它之后填人散列表的同义词结点的查找路径。这是因为各种开放地址法中,空地址单元(即开放地址)都是查找失败的条件。因此在用开放地址法处理冲突的散列表上执行删除操作,只能在被删结点上做删除标记,而不能真正删除结点。
(3)拉链法的缺点