哈希碰撞和哈希冲突
Hash碰撞冲突(哈希碰撞):
我们知道,对象Hash的前提是实现equals()和hashCode()两个方法,那么HashCode()的作用就是保证对象返回唯一hash值,但当两个对象计算值一样时,这就发生了碰撞冲突。
当我们对某个元素进行哈希运算,得到一个存储地址,然后要进行插入的时候,发现已经被其他元素占用了,其实这就是所谓的哈希冲突,也叫哈希碰撞。
哈希冲突如何解决呢?
哈希冲突的解决方案有4种:
1.开放地址法:(再散列法):当关键字key的哈希地址p出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址,直到找出一个不冲突的哈希地址pi ,将相应元素存入其中。
2.再哈希法: 在发生冲突的时候再用另外一个哈希函数算出哈希值,直到算出的哈希值不同为止。
3.链地址法(拉链法):例如HashMap。把同一个散列槽(数组的每一个槽)中的所有元素放到一个链表中。
4.建立公共溢出区法: 在创建哈希表的同时,再额外创建一个公共溢出区,专门用来存放发生哈希冲突的元素。查找时,先从哈希表查,查不到再去公共溢出区查。
拉链法方法:我们拿到一个索引首先计算其在散列函数作用下映射出来的索引,如果索引没有元素,直接插入;如果有元素,但是key值和我们要插入的数据不一样,我们就把key value键值对插入链表头;
如果存在和我们要插入数据相同key的键值对,我们就把value进行更换。
常见的哈希算法
哈希表的组成取决于哈希算法,也就是哈希函数的构成,下面列举几种常见的哈希算法。
1) 直接定址法
- 取关键字或关键字的某个线性函数值为散列地址。
- 即 f(key) = key 或 f(key) = a*key + b,其中a和b为常数。
2) 除留余数法
- 取关键字被某个不大于散列表长度 m 的数 p 求余,得到的作为散列地址。
- 即 f(key) = key % p, p < m。这是最为常见的一种哈希算法。
3) 数字分析法
- 当关键字的位数大于地址的位数,对关键字的各位分布进行分析,选出分布均匀的任意几位作为散列地址。
- 仅适用于所有关键字都已知的情况下,根据实际应用确定要选取的部分,尽量避免发生冲突。
4) 平方取中法
- 先计算出关键字值的平方,然后取平方值中间几位作为散列地址。
- 随机分布的关键字,得到的散列地址也是随机分布的。
5) 随机数法
- 选择一个随机函数,把关键字的随机函数值作为它的哈希值。
- 通常当关键字的长度不等时用这种方法。
学海无涯 代码作伴