第9章 哈希(散列)查找(理论)

【哈希函数的构造】

1、直接定址法

取关键字或关键字的某个线性函数作哈希地址,即 H ( k e y ) = k e y H(key)=key H ( k e y ) = a k e y + b H(key)=a·key+b (a, b为常数)

特点:直接定址法所得地址集合与关键字集合大小相等,不会发生冲突,但实际中很少使用。

2、数字分析法

对关键字进行分析,取关键字的若干位或组合作为哈希地址。

特点:适用于关键字位数比哈希地址位数大,且可能出现的关键字事先知道的情况。

3、平方取中法

将关键字平方后取中间几位作为哈希地址。

特点:一个数平方后中间几位和数的每一位都有关,则由随机分布的关键字得到的散列地址也是随机的。散列函数所取的位数由散列表的长度决定。这种方法适于不知道全部关键字情况,是一种较为常用的方法。

4、折叠法

将关键字分割成位数相同的几部分(最后一部分可以不同),然后取这几部分的叠加和作为哈希地址。

数位叠加有移位叠加和间界叠加两种。

5、除留余数法(常用)

取关键字被某个不大于哈希表表长 m m 的数 p p 除后所得余数作哈希地址,即 H ( k e y ) = k e y   m o d   p H(key)=key \ mod \ p ( p m ) (p \leq m)

特点:利用这种方法的关键是 p p 的选取, p p 选的不好,容易产生同义词。

6、随机数法

取关键字的随机函数值作哈希地址,即 H ( k e y ) = r a n d o m ( k e y ) H(key)=random(key)

特点:当散列表中关键字长度不等时,该方法比较合适。

【冲突处理的方法】

1、开放定址法

基本方法:当冲突发生时,形成某个探测序列;按此序列逐个探测散列表中的其他地址,直到找到给定的关键字或一个空地址(开放的地址)为止,将发生冲突的记录放到该地址中。

散列地址的计算公式是:
H i ( k e y ) = ( H ( k e y ) + d i + m )   m o d   m i = 1 , 2 , , k ( k m 1 ) H_i(key)=(H(key)+d_i+m) \ mod \ m,i=1, 2, … , k (k \leq m-1)

其中: H ( k e y ) H(key) :哈希函数; m m :散列表长度; d i d_i :第i次探测时的增量序列;
H i ( k e y ) H_i(key) :经第 i i 次探测后得到的散列地址。

(1)线性探测法

将散列表 T [ 0 m 1 ] T[0 …m-1] 看成循环向量。当发生冲突时,从初次发生冲突的位置依次向后探测其他的地址。

增量序列为: d i = 1 , 2 , 3 , , m 1 d_i=1, 2, 3, …, m-1

设初次发生冲突的地址是 h h ,则依次探测 T [ h + 1 ] T [ h + 2 ] T[h+1],T[h+2]…, 直到 T [ m 1 ] T[m-1] 时又循环到表头,再次探测 T [ 0 ] T [ 1 ] T[0],T[1]…, 直到 T [ h 1 ] T[h-1]

探测过程终止的情况是:

  1. 探测到的地址为空:表中没有记录。若是查找则失败;若是插入则将记录写入该地址
  2. 探测到的地址有给定的关键字:若是查找则成功;若是插入则失败;
  3. 直到T[h]:仍未探测到空地址或给定的关键字,散列表满。

(2)二次探测法

增量序列为: d i = 1 ² , 1 ² , 2 ² , 2 ² , 3 ² , ± k ² d_i=1²,-1²,2²,-2²,3²,……±k² ( k m / 2 ) (k \leq ⌊m/2⌋)

(3)伪随机探测法

增量序列使用一个伪随机函数来产生一个落在闭区间 [ 1 m 1 ] [1,m-1] 的随机序列。

2、再哈希法

构造若干个哈希函数,当发生冲突时,利用不同的哈希函数再计算下一个新哈希地址,直到不发生冲突为止。
即: H i = R H i ( k e y )   i = 1 , 2 , , k H_i=RH_i(key) \ i=1, 2, …, k

其中, R H i RH_i :一组不同的哈希函数。第一次发生冲突时,用 R H 1 RH_1 计算,第二次发生冲突时,用 R H 2 RH_2 计算 … 依此类推直到得到某个 H i H_i 不再冲突为止。

3、链地址法

方法:将所有关键字为同义词(散列地址相同)的记录存储在一个单链表中,并用一维数组存放链表的头指针。

设散列表长为 m m ,定义一个一维指针数组: R e c N o d e l i n k h a s h [ m ] RecNode *linkhash[m]

其中 R e c N o d e RecNode 是结点类型,每个分量的初值为空。凡散列地址为 k k 的记录都插入到以 l i n k h a s h [ k ] linkhash[k] 为头指针的链表中,插入位置可以在表头或表尾或按关键字排序插入。

4、建立公共溢出区

方法:在基本散列表之外,另外设立一个溢出表保存与基本表中记录冲突的所有记录。

设散列表长为 m m ,设立基本散列表 h a s h t a b l e [ m ] hashtable[m] ,每个分量保存一个记录;溢出表 o v e r t a b l e [ m ] overtable[m] ,一旦某个记录的散列地址发生冲突,都填入溢出表中。

发布了674 篇原创文章 · 获赞 103 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_42815188/article/details/103640194