散列函数和冲突处理办法

散列函数,(也叫哈希函数,台湾称杂凑函数)是一个将(通常)较大的定义域内容映射到一个(通常)较小的值域内的函数,散列函数是一个公开的函数,它将任意长的信息映射到一个固定长度的信息的函数。
构造散列函数的目标是使散列地址尽可能均匀地分布在散列空间上,同时使计算尽可能简单,以节省计算时间。根据关键字的结构和分布不同,可构造出与之适应的各不相同的散列函数,这里只介绍较常用的几种,其中又以介绍除留余数法为主。在下面的讨论中,假定关键字均为整型数,若不是整型数则要设法把它转换为整型数后再进行运算。
1.直接定址法
直接定址法是以关键字K本身或关键字加上某个数值常量C作为散列地址的方法。对应的散列函数h(K)为:
h(K)=K+C
若C为O,则散列地址就是关键字本身。
这种方法计算最简单,并且没有冲突发生,若有冲突发生,则表明是关键字错误。它适应于关键字的分布基本连续的情况,若关键字分布不连续,空号较多,将造成存储空间的浪费。
2.除留余数法
除留余数法是用关键字K除以散列表长度m所得余数作为散列地址的方法。对应的散列函数h(K)为:
h(K)=k%m
这种方法在上面的例中已经使用过。除留余数法计算较简单,适用范围广,是一种最常使用的方法。这种方法的关键是选好m,使得每一个关键字通过该函数转换后映射到散列空间上任一地址的概率都相等,从而尽可能减少发生冲突的可能性。例如,取m为奇数,比取m为偶数要好。因为当m为偶数时,它总是把关键字为偶数的元素散列到偶数单元中,把关键字为奇数的元素散列到奇数单元中,即把_个元素只散列到一一半的存储空间中;当m为奇数时就不会出现这种问题,它能够把一个元素散列到整个存储空间中。结合处理冲突时对m的要求,最好取散列表的长度m为一个素数(即除l和本身之外,不能被任何数整除的数)。当然,要确保m的值大于等于待散列的线性表的长度n,根据装填因子a最好为在0.6至O.9之间,所以m应取1.1n至1.7n之间的一个素数。例如,若n=lOO,则m最好取l 1 3、127、139、143等素数。
另外,当关键字K为一个字符串时,需要把它设法转换为一个整数,然后再用这个整数整除以m得到余数,即散列地址。下面的Hash(K,m)函数就能够求出关键字K为字符串时的散列地址。在这里,采用的把字符串K转换为整数的过程是:首先求出K的长度,即所含的字符个数,接着把每个字符的ASCII码(即该字符的整数值)累加到无符号整型量h上,并在每次累加之前把h的值左移3个二进制位,即扩大8倍。
3.数字分析法
数字分析法是取关键字中某些取值较分散的数字位作为散列地址的方法。它适合于所有关键字已知,并对关键字中每一位的取值分布情况作出了分析。例如,有一组关键字为(92317602,92326875,92739628,92343634,92706816,92774638,92381262, 92394220),通过分析可知,每个关键字从左到右的第1,2,3位和第6位取值较集中,不宜作散列地址。剩余的第4,5,7和8位取值较分散,可根据实际需要取其中的若干位作为散列地址。若取最后两位作为散列地址,则散列地址的集合为(2,75,28,34,16,38,62,20)。
4.平方取中法
平方取中法是取关键字平方的中间几位作为散列地址的方法,具体取多少位视实际要求而定。一个数平方后的中间几位和数的每一位都有关。从而可知,由平方取中法得到的散列地址同关键字的每一位都有关,使得散列地址具有较好的分散性。平方取中法适应于关键字中的每一位取值都不够分散或者较分散的位数小于散列地址所需要的位数的情况。
5.折叠法
折叠法是首先将关键字分割成位数相同的几段(最后一段的位数若不足应补0),段的位数取决于散列地址的位数,由实际需要而定,然后将它们的叠加和(舍去最高位进位)作为散列地址的方法。例如一个关键字K=68242324,散列地址为3位,则将此关键字从左到右每三位一段进行划分,得到的三段为682,423和240,叠加和为682+423+240=345,此值就是存储关键字为68242324元素的散列地址。折叠法适应于关键字的位数较多,而所需的散列地址的位数又较少,同时关键字中每一位的取值又较集中的情况。
以上是散列函数的常见算法,
当发生冲突时候,又有很多冲突处理办法,应该让散列地址尽可能均匀地分布在散列空间上,才能加快我们的查找速度。
4.hashCode 与 equals
简而言之就是:

如果两个对象相等,则hashcode(根据hash算法得到的逻辑地址,但是他们的物理地址一定不相等)一定也是相同的
两个对象相等,对两个对象分别调用equals方法都返回true
两个对象有相同的hashcode值(因为有hashCode冲突),它们也不一定是相等的
因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
hashCode() 的默认行为是对堆上的对象产生独特值。如果没有重写 hashCode(),则该 class 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值