【Java】哈希冲突(哈希碰撞)


为什么发生哈希冲突(哈希碰撞)

  当向hash表中存放数据时,会使用hash函数计算出对应的hash函数值,即哈希地址,所以会出现不同关键字具有相同hash函数值,即不同数据具有同一hash地址的情况,这个时候就发生了哈希冲突。

能否完全避免哈希冲突

  虽然可以选择不同的哈希函数去避免冲突的产生,但是数据量增长,始终会产生哈希冲突,因此只能尽量减少。

常用处理哈希冲突的方法

  1. 开放地址法
  2. 再哈希地址法
  3. 链地址法
  4. 建立公共溢出区

1.开放地址法

  当产生哈希冲突时,就在哈希表中寻找另一个空的位置存放关键字。如何寻找另一个空的位置,也有不同的规则。

  1. 线性探测再散列
  2. 二次探测再散列
  3. 伪随机探测再散列

1.1线性探测再散列

  当发生哈希冲突时,即某一位置已放了关键字,会查询下一个位置上是否是空的,空的便放入,否则再下一个位置尝试放入直到解决冲突。每次查询下一个未冲突的位置的增量d为1、2、3、4…(不断自增),即不断加上增量d,从而寻找下一个空的位置。
例如:
  关键字(35、74、02、31、39、98、99、100)按哈希函数H(key) = key / 7 和开放地址法中的线性探测处理哈希冲突

  1. 35关键字放在0位置
0123456789
35
  1. 74关键字放在4位置
0123456789
3574
  1. 02关键字放在2位置
0123456789
350274
  1. 31关键字放在3位置
0123456789
35023174
  1. 39关键字应放在(39/7 = 5…4)4位置,但4位置已有关键字,则根据线性探测,下一个空的位置为5,则将39关键字放在5位置
0123456789
3502317439
  1. 类似的情况,98关键字由于0位置已被占用,顺延一位至1位置
0123456789
359802317439
  1. 99关键字应放入1位置,但由于前面位置均已被占用,跳过已占有的所有位置,找到最近的空位,被放入6位置
0123456789
35980231743999
  1. 100关键字同理
0123456789
35980231743999100
缺点:二次聚集

  发现当表中i、i+1、i+2位置上已经填有记录时,下一个哈希地址为i、i+1、i+2、i+3的关键字,都将先填入i+3位置,这种解决哈希冲突过程中,发生的两个第一哈希地址不同的记录,争夺同一个后继哈希地址的现象称之为  二次聚集 ,显然数据量大了后,后续探测距离会特别长,线性探测会造成二次聚集,这对查找不利,但是这也可以保证只要哈希表未填满,总能找到一个不发生哈希冲突的地址。

1.2二次探测再散列

  二次探测再散列也是类似的思路,一旦将填入的位置已有关键字,便会根据规则寻找下一个未被占用的位置,即不断加上增量d,从而寻找下一个空的位置。但规则区分于自增的线性探测,增量d为12 、-12、22、-22 、32、-32
例如:
  同样的关键字(35、74、02、31、39、98、99、100)按哈希函数H(key) = key / 7 和开放地址法中的二次探测再散列处理哈希冲突

  1. 39关键字应放在4位置,但4位置已有关键字,则根据增量d=12,放在4+1=5,5位置上
0123456789
3502317439
  1. 98关键字由于0位置已被占用,根据增量d=12 =1,放在1位置
0123456789
359802317439
  1. 99关键字应放入1位置,但1已被占用,根据增量d=12 =1,放入(1+1)2位置,但2已占用,继续下一个增量d=-12,放入(1-1)0位置,但0已占用。d= 22 = 4,放入(1+4)5位置,但5已占用,继续下一个增量。d= -22 已越界,继续下一个增量d= 32 = 9,放入(1+9)10位置
012345678910
35980231743999
  1. 100关键字,尝试放入位置为2、(+1)3、(-1)1、(+4)6
012345678910
35980231743910099

  二次探测再散列使用并不多,因为当增量d非常大时,每一个跨度都非常大,需要跨过很多空地址。

1.3伪随机探测再散列

  取决于伪随机数列


2.再哈希地址法

  当产生哈希地址冲突时,使用另一个不同的哈希函数计算哈希函数地址直到冲突不再产生。这不容易产生聚集,但会有计算时间的额外开销。


3.链地址法

  建立一个单链表(同一线性链表),链表上的数据均为相同的哈希地址x,该链表中的数据插入位置可以在头尾或中间,保持同意立案表中按关键字有序,将同一链表的头指针放在哈希表中x的位置。
例如:
  关键字(01、14、20、27、55、68)按哈希函数H(key)= key MOD 13 和链地址法处理哈希冲突,得到的哈希表如图所示
在这里插入图片描述
                (链地址法得到的哈希表)


4.建立公共溢出区

  建立溢出表和基本表,出现与基本表有冲突的数据,无论哈希函数计算得到的哈希地址是什么,一旦发生冲突,都填入溢出表。会有额外的空间开销。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值