YAZONG 我的开源

(数据结构)第十一讲-散列查找(11.2 散列函数的构造方法)

  , ,
0 评论0 浏览

11.2.1 数字关键词的散列函数构造

目的

image.png

直接定址法

image.png

把散列函数设计成一个线性函数。

关键词是年份,把值映射成0-21的地址空间。

这里只有22个元素。

(最常用)除留余数法

image.png

把关键词进行求余计算,把一个大的整数转换成一个小的整数,相当于散列表的地址。

为了散列表映射均匀,一般会把散列表的总数P设置成素数。

数字分析法

关键词可能有许多位数组成,每一位在对象中的变化情况不同,有的某一位可能一直都是不动的,有的某些位会随机变化。

数字分析法希望分析出对象的关键字在每一位上的表现,把这些能够随机变化的这些位取出来组成地址,达到映射均匀的目的。

====手机号案例

image.png

对于同一地区来说,手机号前几位可能都差不多,变化最大的是后四位,可以把手机号的后四位作为地址。

image.png

最终获得地址。

====身份证号案例

image.png

身份证号中的每一位都有特殊含义,蓝色数字是变化比较大的,提出来。

[6]-6:区县变化大。

[10]-0:生日都是199X年的,最后一位变化大。

[14]-8:日期十位变化大。

[16]-4:辖区序号变化大。

[17]-1:辖区序号变化大。

[18]-9:数字或字符变化大。

image.png

计算h1(key)拿到前五位60841组成五位数(十进制)。

计算h(key)再把h1(key)组合进来。

折叠法

image.png

总共8位,从后往前,每段拆成3位,不够前面补0。

最后取计算结果的后三位作为地址。

也是希望结果能被更多的位数所影响。

平方取中法

image.png

希望计算的函数值,每一位都能被影响,即每一位的变化都能影响到最后的函数结果值,比如尾数。

取平方值的中间的三位数,也是希望结果能被更多的位数所影响。

11.2.2 字符串关键词的散列函数构造

image.png

把字符串对象映射为整数,每一个字符是一个ASCII编码,所有整数相加,求余得到散列值。

但这样的方法也会有很多冲突。

更致命的问题,ASCII主要用到7位,编码范围0-127,比如变量名是10位,那么每个字符值的变化范围是0-1270,但变量名的变化范围更广大,如果用一个很窄的值计算结果来对付一个很广的变量名的范围,那么这样的哈希函数就很容易产生聚集。

image.png

比如abcde,取前面3个字符,通过27进制来计算。

用27,是因为26个字符之后可能会有空格,所以可能有27个字符。

这样仍然会产生冲突,因为变量名很长,前三位是一样的。

另外,可能会造成地址空间浪费,三个字符变化是26的三次方,实际统计前三位一般出现的情况是3000种,实际上考虑26的三次方会导致地址空间浪费。

进一步考虑,不只考虑前三个字符组合,而是把所有的字符都组合,3、4、5、6位等都考虑进去。

image.png

比如把字符abcde的序列,考虑32进制来计算。

image.png

级数求和:((((a*32+b)*32+c)*32+d)*32+e),这样可以减少乘法的次数,这里4次,原来10次。

更巧妙的方法:x << 5 ,左移5位就是X * 32。

源码:

第1次循环key不等于0,指向”abcde”中的”a”,0<<5=0,即h1=0 + a。

第2次循环key不等于0,指向”abcde”中的”b”,即h2=h1<<5 + b。

依次处理,最终结果h直接求余即可。


标题:(数据结构)第十一讲-散列查找(11.2 散列函数的构造方法)
作者:yazong
地址:https://blog.llyweb.com/articles/2023/10/22/1697984883679.html