发布时间:2025-05-06 13:17:15 点击量:
HASH GAME - Online Skill Game GET 300
* * 1、哈希表的定义 2、哈希函数的构造方法 3、处理冲突的方法 4、哈希表的查找及分析 在前面讨论的各种结构中,记录在各种结构中的相对位置是随机的,和在记录的关键字之间不存在有确定的关系,因此在查找记录是需要进行一系列和关键字的比较。这一类超找方法建立在“比较”的基础上。而理想的情况是不希望进行任何的比较,一次寻去便能得到所查记录。那就必须在记录的存储位置和它的关键字之间建立一种确定的关系f使每个关键字和结构中有一个唯一的存储位置与之相对应。我们称这个对应关系f为哈希函数,而按这个思想建立的表为哈希表。 哈希表的定义 然而在很多的时候,对不同的关键字可能得到同一哈希地址,这种现象称为冲突。 在一般情况下,冲突只能尽量的减少,而不能完全的避免。 因此根据根据设定的哈希函数 H(key)和处理冲突的方法将一组关键字映像到一个有限的连续的地址集上,并以关键字在地址集中得“像”作为记录在表中的存储位置,这种表便称为哈希表,这一映像过程称为哈希造表或散列,所得存储位置为哈希地址或散列地址。 哈希函数的构造方法 常用的构造哈希函数的方法有: 1、直接定址法 2、数字分析法 3、平方取中法 4、折叠法 5、除留余数法 6、随机数法 直接定址法:取关键字或关键字的某个线性函数值为哈希地址。即H(key)或H(key)=a*key=b。其中a和b为常(这种哈希函数叫做自身函数)。 数字分析法:假设关键字是以r为基的数(如:以10为基的十进制数)并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。 平方取中法:取关键字平方后的中间几位作为哈希地址。得到的哈希地址是随机的,取得位数由表长来决定。 折叠法:将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。 除留余数法:取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。即H(key)=key MOD p,p=m 这是一种最简单,也是最常用的方法。它不仅可以对关键字直接取模,也可以在折叠平方等运算之后取模。P应该取小于表长的最大素数。 随机数法:选择一个随机函数,取关键字的随机函数值为它的哈希地址,即H(key)=random(key),其中random为随机函数。通常当关键字长度不等于时采用此法构造哈希函数比较恰当。 处理冲突的方法 通常用的处理冲突的方法有: 1、开放定址法 2、在哈希法 3、链地址法 4、建立一个公共溢出区 开放定址法:Hi=(H(key)+ di )MOD m i=1,2,…,k(k=m -1)其中H(key)为哈希函数;m为哈希表长;di增量序列。 在哈希法:hi=RHi(key) i=1,2,…,k RHi均为不同的哈希函数,记载同义词产生地址冲突时计算另一个哈希函数地址,直接到冲突不在发生。这种方法不易产生”聚集“,但增加了计算的时间。 链地址法:将所有关键字为同义词的记录存储在同一线性表中。假设某哈希函数产生的哈希地址在区间[0,m-1]上,则设立一个指针型变量Chain ChainHash[m ];其每个分量的初始状态都是空指针。凡哈希地址为i的记录都插入到头指针为ChainHash[i ];的链表中。在链表中的插入位置可以在表头或表尾,也可以在中间,以保持同义词在同一线性表中按关键字是有序的。 建立一个公共溢出区:假设哈希函数的值域为[0,m-1],则设向量HashTable[0..m-1]为基本表,每个分量存放一个记录,令设立向量OverTable[0..v]为溢出表。所有关键字和基本表中关键字为同义词的记录,不管他们由哈希函数得到的哈希地址是什么,一旦发生冲突,都填入溢出表。 哈希表的查找及分析 哈希表的查找:在哈希表上进行查找的过程和哈希造表的过程基本一致。给定k值,根据造表时设定的哈希函数求的哈希地址,若表中此位置上没有记录,则查找不成功;否则比较关键字若和给定值相等,则查找成功;否则根据造表时设定的处理冲突的方法找下一个定址,直至哈希表中某个位置为空或者表中所填记录的关键字等于给定值时为止。 哈希表的性能分析:从哈希表的查找过程来看,虽然哈希表在关键字与记录的存储位置之间建立了直接映像,但由于冲突的产生,使得哈希表的查找过程仍然是一个给定值和关键字进行比较的过程,因此,仍需以平均查找长度作为衡量哈希表的查找效率的量度。但是对于均匀的哈希函数可以假定:不同的哈希函数对同一组随机的关键字,产生冲突的可能性相同,因为一般情况下设定的哈希函数时均匀的,则可不考虑它对平均查找长度的影响。 例如:有一个从1到100岁的人口数字统计表,其中,年龄作为关键字,哈希函数取关键字自身。 地址 年龄 人数 … 01 02 03 … 25 26 27 … 100 1 2 3 … 25 26 27 … 100 3000 2000 5000 … 1050 … … … … 直接定址哈希函数例子 这样若要查询25岁的人有多少,则只要查表的第25项即可。 例如有80个记录,其关键字为8位十进制数。假设哈希表的表长为10010则可取两位十进制数组成哈希地址。原则是使得到的哈希地址尽量避免产生冲突,则需从分析这80个关键字着手,假设这80个关键字中的一部分如下所列:37… … 8 2 3 4 5 6 7 1 对关键字全体的分析中我们发现:第一二位都是“8 1”,第三位只能取1、2、3或4,第八位只能取2、5或7,因此这四位都不可取。由于中间的四位可看成是近乎随机的,因此可取其中任意两位,或取其中两位与另两位的叠加求和后舍去进位作为哈希地址。 例如:为BASIC源程序中的标示符建立一个哈希表。假设BASIC语言中允许的标识符为一个字母,或一个数字和一个字母。如图所示: ABC…Z012…9 01 02 03 32 60 61 62 71 记录 关键字 (关键字) 2 哈希地址 A I J I0 P1 P2 Q1 Q2 Q3 0100 1100 1200 1160 2061 2062 2161 2162 2163 0010000 1210000 1440000 1370400 4310541 4314704 4734741 4741304 4745651 010 210 440 370 310 314 734 742 745 折叠法中数位叠加可以有移位叠加和间界叠加两种方法。 例如:每一种西文图书都有一个国际标准图书编号,用移位叠加和间界叠加求得国际标准图书编号0-442-20586-4的哈希地址分别为 5864 4220 +) 04 10088 H(key)=0088 5864 0224 +) 04 6092 H(key)=6092 移位叠加:将分割后的每一部分的最低位对齐然后相加。 间界叠加:从一端向另一端沿分割界来回折叠,对齐相加。 di为增量序列,可有下列三种取法:(1)di=1,2,3…,m-1,称线,…,+k,-k,(k=m/2),称二次探测再散列;(3)di=伪随机数序列,称伪随机探测再散列。 2 2 2 2 2 2 2 29 17 60 0 1 2 3 4 5 6 7 8 9 10 38 29 17 60 29 17 60 38 29 17 60 38 (a)插入前 (b)线性探测再散列 (c)二次探测再散列 (d)伪随机探测再散列,伪随机数列9,… 用开前后的放地址处理冲突时,关键字为38的记录插入哈希表 例如:已知一组关键字为(19,14,23,01,68,20,84,27,55,11,10,79) 则按哈希函数H(key)=key MOD 13和链地址法处理冲突构造所得的哈希表如图所示。 0 1 2 3 4 5 6 7 8 9 10 11 12 01 14 27 79 55 68 19 84 20 10 23 11 链地址法处理冲突时的哈希表 (同一链表中关键字自小至大有序) *