关于哈希函数的构造方法

        构造哈希函数的方法很多。在介绍各种方法之前,首先需要明确什么是“好”的哈希函数。

        若对于关键字集合中的任一个关键字,经哈希函数映像到地址集合中任何一个地址的概率是相等的,则称此类哈希函数为均匀的(Uniform)哈希函数。换句话说,就是使关键字经过哈希函数得到一个“随机的地址”,以便使一组关键字的哈希地址均匀分布在整个地址区间中,从而减少冲突。

        常用的构造哈希函数的方法有:

1.直接定址法

        取关键字或关键字的某个线性函数值为哈希地址。即:

        H(key)=key或H(key)=a\bulletkey+b

        其中a和b为常数(这种哈希函数叫做自身函数)。

        例如:有一个从1岁到100岁的人口数字统计表,其中,年龄作为关键字,哈希函数取关键字自身。如表1所示:

关于哈希函数的构造方法_第1张图片 标图1 直接定址哈希函数例之一题

        这样,若要询问25岁的人有多少,则只要查表的第25项即可。

        又如:有一个解放后出生的人口调查表,关键字是年份,哈希函数取关键字加一常数:H(key)-key+(-1948),如表2所示。

关于哈希函数的构造方法_第2张图片 图2 直接定址哈希函数列之二

        这样,若要查1970年出生的人数,则只要查第(1970—1948)=22项即可。

        由于直接定址所得地址集合和关键字集合的大小相同。因此,对于不同的关键字不会发生冲突。但实际中能使用这种哈希函数的情况很少。

2.数字分析法

        假设关键字是以r为基的数(如:以10为基的十进制数),并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。

        例如有80个记录,其关键字为8位十进制数。假设哈希表的表长为100%,则可取两位十进制数组成哈希地址。'取哪两位?原则是使得到的哈希地址尽量避免产生冲突,则需从分析这80个关键字着手。假设这80个关键字中的一部分如下所列:

关于哈希函数的构造方法_第3张图片

        对关键字全体的分析中我们发现:第①②位都是“8 1”,第③位只可能取1、2、3或4,第⑧位只可能取2,5或7,因此这4位都不可取。由于中间的4位可看成是近乎随机的,因此可取其中任意两位,或取其中两位与另外两位的叠加求和后舍去进位作为哈希地址。

3.平方取中法

        取关键字平方后的中间几位为哈希地址。这是一种较常用的构造哈希函数的方法。通常在选定哈希函数时不一定能知道关键字的全部情况,取其中哪几位也不一定合适,而一个数平方后的中间几位数和数的每一位都相关,由此使随机分布的关键字得到的哈希地址也是随机的。取的位数由表长决定。

        例如:为 BASIC源程序中的标识符建立一个哈希表。假设BASIC语言中允许的标识符为一个字母,或一个字母和一个数字。在计算机内可用两位八进制数表示字母和数字,如图3(a)所示。取标识符在计算机中的八进制数为它的关键字。假设表长为512=2^{9},则可取关键字平方后的中间9位二进制数为哈希地址。例如,图3(b)列出了一些标识符及它们的哈希地址。

图3(a)字符的八进制表示对照表

关于哈希函数的构造方法_第4张图片 标题图3(b)标识符及其哈希地址

4.折叠法

        将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址,这方法称为折叠法(folding)。关键字位数很多,而且关键字中每一-位上数字分布大致均匀时,可以采用折叠法得到哈希地址。

        例如:每一种西文图书都有一个国际标准图书编号(ISBN),它是一个10位的十进制数字,若要以它作关键字建立一个哈希表,当馆藏书种类不到10 000时,可采用折叠法构造一个四位数的哈希函数。在折叠法中数位叠加可以有移位叠加和间界叠加两种方法。移位叠加是将分割后的每一部分的最低位对齐,然后相加;间界叠加是从一端向另一端沿分割界来回折叠,然后对齐相加。如国际标准图书编号0-442-20586-4的哈希地址分别如图4(a)和(b)所示。

关于哈希函数的构造方法_第5张图片 图4 由折叠法求得哈希地址(a)移位叠加 (b)间界叠加

5.除留余数发

        取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。即

        H(key) = key  MOD  p, p\leqm

        这是一种最简单,也最常用的构造哈希函数的方法。它不仅可以对关键字直接取模(MOD),也可在折叠,平方取中等运算之后取模。

        值得注意的是,在使用除留余数法时,对p的选择很重要。若p选的不好,容易产生同义词。请看下面3个例子。

        假设取标识符在计算机中的二进制表示为它的关键字(标识符中每个字母均用两位八进制数表示),然后对p=2^{6}取模。这个运算在计算机中只要移位便可实现,将关键字左移直至只留下最低的6位二进制数。这等于将关键字的所有高位值都忽略不计。因而使得所有最后一个字符相同的标识符,如a1,i1 , temp1,cp1等均成为同义词。

        若p含有质因子Pf,则所有含有pf因子的关键字的哈希地址均为pf的倍数。例如﹐当p=21( =3×7)时,下列含因子7的关键字对21取模的哈希地址均为7的倍数。

        假设有两个标识符xy 和yx,其中x,y均为字符,又假设它们的机器代码(6位二进制数)分别为c(z)和c(y),则上述两个标识符的关键字分别为

        key1 = 2^{6}c(x) + c(y) 和key2 = 2^{6}c(y) + c(x)

        假设用除留余数法求哈希地址,且力=tq,t是某个常数,q是某个质数。则当q=3时,这两个关键字将被散列在差为3的地址上。因为

关于哈希函数的构造方法_第6张图片

        由众人的经验得知:一般情况下,可以选p为质数或不包含小于20的质因数的合数。

6.随机数法

        选择一个随机函数,取关键字的随机函数值为它的哈希地址,即 H(key)=random(key),其中random为随机函数。通常﹐当关键字长度不等时采用此法构造哈希函数较恰当。

        实际工作中需视不同的情况采用不同的哈希函数。通常,考虑的因素有:

        (1)计算哈希函数所需时间(包括硬件指令的因素);

        (2)关键字的长度;

        (3)哈希表的大小;

        (4)关键字的分布情况;

        (5)记录的查找频率。

然后今天就讲到这里啦,大家记得点赞收藏,分享转发,关注小哥哥哦! 最后,如果你想学或者正在学C/C++编程,可以加入小编的编程学习C/C++企鹅圈https://jq.qq.com/?_wv=1027&k=vLNylJeG

    

你可能感兴趣的:(c++,开发语言,学习,c语言,哈希算法)