Campus Guider校园导航系统 Hash算法分析

Campus Guider校园导航系统是一款简单的Windows 8平台应用,开发过程中采用Hash表存储校园地点列表,现笔者将项目中的hash算法分析记录如下。

本项目中Hash算法有两条设计思路,两条思路的主要区别在于对冲突处理的方法不同。对于Hash函数H(key)来说,key是汉字字符串。而Hash表的长度和填充因子是相同的。首先,经过数据的收集、统计和整理后,最终确定了校园中142个地点作为应用中的原始数据,将表长确定为347,那么由此计算得的填充因子为0.409。表长由实际数据个数的两倍再乘以系数1.25计算后所得值,再向取一个比该值小的素数而得,即142*2*1.25=355,然后取一个表长下限301,从[301,355]的素数集合中选取冲突产生少、聚集度小的素数(即将这个素数预设为表长后进行Hash造表并观察结果),将其确定为表长。用此法是因为,本项目中的数据都是预知的,可以进行多次测试选取比较好的结果。下面叙述两种设计思路。


思路一 采用开放定址的线性探测再散列的方法处理冲突

Hash函数为:

       当key>2时H(key)=((int)key[1]+(int)key[2]+di)/347(取第2和第3个汉字计算,值为unicode值)di=1,2,3…;

       当key=2时H(key)=( (int)key[0]+(int)key[1]+di)/347(取第1和第2个汉字计算,值为unicode值)di=1,2,3…;

       由于key是地名,所以不存在单字的情况。

       冲突产生时di将加1,依次向后探测空闲地址。

这种方法造表结果如下图所示。Hash函数运算和处理冲突的总次数为211,即在查找成功时,此方法的平均查找长度ASL=211/142。在6处产生了数据聚集(5个及以上数据连续),涉及到53条记录,若目标关键字的Hash地址落在此区域将导致查找效率下降。

 

思路二 采用二次Hash和公共溢出区的方法处理冲突

Hash函数为

    当key>2时H(key)=((int)key[1]+ (int)key[2])*1.618033/277(取第2和第3个汉字计算,值为unicode值);

       当key=2时H(key)=( (int)key[0]+(int)key[1])/275+2(取第1和第2个汉字计算,值为unicode值);

       由于key是地名,所以不存在单字的情况。

       冲突处理:第一次处理,先由key=2时的Hash函数计算得Hash地址,若该地址空间则存储;否则,将该地址记为code,然后进行判断

       当code<138时,code=code/4+277;

       当code>=138时,code=(code-138)/4+312。

       通过这两步取得当前记录在公共溢出区的存储地址。

    其中乘数因子1.618033是为了使得生成的Hash表更加均匀,定义Hash表的后70位空间为公共溢出区,记录先通过往前277个地址中存放,若不成功,则将前277个地址中的前138个地址中产生冲突的记录存放至公共溢出区的前35个地址中,后前277个地址中的后139个地址中产生冲突的记录存放至公共溢出区的后35个地址中。即对一条记录的关键字的处理被限制为3次,至多三次可将一条记录存入Hash表。这种方法造表结果如下图所示。Hash函数运算和处理冲突的总次数为195,即在查找成功时,此方法的平均查找长度ASL=195/142。所有142条记录均已加入Hash表。在查找失败时,任意地址至多计算比较三次即可确定失败,即这种方法即定了查找失败的查找长度。相对上思路一中,在6处数据聚集段(假设每处5条记录聚集),其查找失败的近似平均查找长度为ASL=(6*(6+2)*5/20/(6*5)=4。而在本思路中,查找失败时,近似平均查找长度为ASL=(6*5*3)/(6*5)=3。观察下图可可,在公共溢出区中存储了10条记录,其填充因子α L=1/7,约为0.143,在前277个存储地址中有132条数据,其填充因子α M=132/277,约为0.477,总填充因子仍为0.409。

你可能感兴趣的:(算法,hash,应用,导航)