java 哈希冲突

本文主要讨论解决哈希冲突的几种方法。

什么是哈希冲突?

由于哈希算法被计算的数据是无限的,而计算后的结果范围有限,因此总会存在不同的数据经过计算后得到的值相同,这就是哈希冲突。(两个不同的数据计算后的结果一样)

解决哈希冲突的几种方法

大致有四种方法:
    1. 开放定址法(再散列法)
        线行探查法
        平方探查法
        双散列函数探查法
    2. 链地址法(拉链法)
    3. 再哈希法
    4. 建立公共溢出区
1. 开放定址法

从发生冲突的那个单元起,按照一定的次序,从哈希表中找到一个空闲的单元,然后把发生冲突的元素存入到该单元的一种方法。

开发定址法需要的表长度要大于等于所需要存放的元素

在开发定址法中解决冲突的方法有:
    1. 线行探查法
    2. 平方探查法
    3. 双散列探查法
开放定址法缺点:
    删除元素的时候不能真的删除,否则会引起查找错误。
    只能做一个标记,直到有下个元素插入才能真正删除该元素。

1.1 线行探查法

线行探查法是开放定址法中最简单的冲突处理方法,它从发生冲突的单元起,依次判断下一个单元是否为空,当达到最后一个单元时,再从表首依次判断。直到碰到空闲的单元或者探查完全部单元为止。

1.2 平方探查法

平方探查法即是发生冲突时,用发生冲突的单元d[i], 加上 1²、 2²等。即d[i] + 1²,d[i] + 2², d[i] + 3²…直到找到空闲单元。

在实际操作中,平方探查法不能探查到全部剩余的单元。不过在实际应用中,能探查到一半单元也就可以了。若探查到一半单元仍找不到一个空闲单元,表明此散列表太满,应该重新建立。

1.3 双散列函数探查法

这种方法使用两个散列函数hl和h2。其中hl和前面的h一样,以关键字为自变量,产生一个0至m—l之间的数作为散列地址;h2也以关键字为自变量,产生一个l至m—1之间的、并和m互素的数(即m不能被该数整除)作为探查序列的地址增量(即步长),探查序列的步长值是固定值l;对于平方探查法,探查序列的步长值是探查次数i的两倍减l;对于双散列函数探查法,其探查序列的步长值是同一关键字的另一散列函数的值。

2. 链地址法

链接地址法的思路是将哈希值相同的元素构成一个同义词的单链表,并将单链表的头指针存放在哈希表的第i个单元中,查找、插入和删除主要在同义词链表中进行。链表法适用于经常进行插入和删除的情况。

3. 再哈希法

就是同时构造多个不同的哈希函数:
Hi = RHi(key) i= 1,2,3 … k;
当H1 = RH1(key) 发生冲突时,再用H2 = RH2(key) 进行计算,直到冲突不再产生,这种方法不易产生聚集,但是增加了计算时间。

4. 建立公共溢出区

将哈希表分为公共表和溢出表,当溢出发生时,将所有溢出数据统一放到溢出区。

参考

  • https://www.jianshu.com/p/4d3cb99d7580
  • https://www.jianshu.com/p/7e7f52a49ffc

你可能感兴趣的:(java)