Java集合(二):hash、hashcode和equals

hash

Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,该输出就是散列值(Hashcode)。这种变换是一种压缩映射,也即哈希值所占的空间一般来说远小于输入值的空间,不同的输入可能会哈希出相同的输出(概率很小)。存放记录的数组称做散列表(Hash Table),又叫哈希表。JAVA函数hashCode()即请求对象的哈希值
根据同一散列函数计算出的散列值如果不同,那么输入值肯定也不同。但是,根据同一散列函数计算出的散列值如果相同,输入值不一定相同
两个不同的输入值,根据同一散列函数计算出的散列值相同的现象叫做hash碰撞

Hash的优点
先分类再查找,通过计算缩小范围,加快查找速度

散列算法(Hash函数)
Hash通过Hash函数,将Key值映射为地址,Address = F[key];
常见的几种Hash函数:直接定址法、数字分析法、平方取中法、折叠法、随机数法、除留余数法

  1. 直接定址法
    取Key或者Key的某个线性函数值为散列地址。Hash(k) = k,或者Hash(k) = a*k + b, (a\b均为常数).
    如下例所示:a = 1/100,b = -5.
    在这里插入图片描述
  2. 数字分析法
    假设关键字集合中的每个关键字都是由 s 位数字组成 (u1, u2, …, us),分析关键字集中的全体,并从中提取分布均匀的若干位或它们的组合作为地址。

数字分析法是取数据元素关键字中某些取值较均匀的数字位作为哈希地址的方法。即当关键字的位数很多时,可以通过对关键字的各位进行分析,丢掉分布不均匀的位,作为哈希值。它只适合于所有关键字值已知的情况。通过分析分布情况把关键字取值区间转化为一个较小的关键字取值区间。

例:要构造一个数据元素个数n=80,哈希长度m=100的哈希表。不失一般性,我们这里只给出其中8个关键字进行分析,8个关键字如下所示:

K1=61317602 K2=61326875 K3=62739628 K4=61343634

K5=62706815 K6=62774638 K7=61381262 K8=61394220

分析上述8个关键字可知,关键字从左到右的第1、2、3、6位取值比较集中,不宜作为哈希地址,剩余的第4、5、7、8位取值较均匀,可选取其中的两位作为哈希地址。设选取最后两位作为哈希地址,则这8个关键字的哈希地址分别为:2,75,28,34,15,38,62,20。
此法适于:能预先估计出全体关键字的每一位上各种数字出现的频度。

3.平方取中法
这是一种常用的哈希函数构造方法。这个方法是先取关键字的平方,然后根据可使用空间的大小,选取平方数是中间几位为哈希地址。

哈希函数 H(key)=“key2的中间几位”因为这种方法的原理是通过取平方扩大差别,平方值的中间几位和这个数的每一位都相关,则对不同的关键字得到的哈希函数值不易产生冲突,由此产生的哈希地址也较为均匀。

例:若设哈希表长为1000则可取关键字平方值的中间三位,如图所示:
在这里插入图片描述
此法适于:关键字中的每一位都有某些数字重复出现频度很高的现象

4.折叠法
将关键字分割成若干部分,然后取它们的叠加和为哈希地址。两种叠加处理的方法:移位叠加:将分 割后的几部分低位对齐相加;边界叠加:从一端沿分割界来回折叠,然后对齐相加。

所谓折叠法是将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位),这方法称为折叠法。这种方法适用于关键字位数较多,而且关键字中每一位上数字分布大致均匀的情况。

折叠法中数位折叠又分为移位叠加和边界叠加两种方法,移位叠加是将分割后是每一部分的最低位对齐,然后相加;边界叠加是从一端向另一端沿分割界来回折叠,然后对齐相加。

例4,当哈希表长为1000时,关键字key=110108331119891,允许的地址空间为三位十进制数,则这两种叠加情况如图:
在这里插入图片描述
用移位叠加得到的哈希地址是559,而用边界叠加所得到的哈希地址是44。如果关键字不是数值而是字符串,则可先转化为数。转化的办法可以用ASCⅡ字符或字符的次序值。
此法适于:关键字的数字位数特别多。

  1. 随机数法:
    设定哈希函数为:H(key) = Random(key)其中,Random 为伪随机函数
    此法适于:对长度不等的关键字构造哈希函数。

6.除留余数法:取关键字被某个除数 p 求余,得到的作为散列地址。

即 H(Key) = Key % p; 在这里插入图片描述
哈希冲突
不管选用何种散列函数,不可避免的都会产生不同Key值对应同一个Hash地址的情况,这种情况叫做哈希冲突。

哈希冲突的解决方法

1.开放地址法

当冲突发生时,探测其他位置是否有空地址 (按一定的增量逐个的寻找空的地址),将数据存入。根据探测时使用的增量的取法,分为:线性探测、平方探测、伪随机探测等。

新的Hash地址函数为 Hash_new (Key) = (Hash(Key) + d i) mod m;i = 1,2…k (k<= m-1).m表示集合的元素数,i表示已经探测的次数。

(1)线性探测(Linear Probing),d i = a * i + b; a\b为常数。相当于逐个探测地址列表,直到找到一个空置的,将数据放入。
例子:

Key集合为(15,36,25,46,75),采用除留余数法,模10 ,冲突时采用线性探测法(d+i)%10 ;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值