哈希冲突的解决方法

1.基本概念

哈希算法:根据设定的哈希函数H(key)和处理冲突方法将一组关键字映象到一个有限的地址区间上的算法。也称为散列算法、杂凑算法。
哈希表:数据通过哈希算法以后获得的集合。这样关键字和数据在集合中的位置存在必定的关系,能够根据这种关系快速查询。
非哈希表:与哈希表相对应,集合中的 数据和其存放位置没任何关联关系的集合。java

因而可知,哈希算法是一种特殊的算法,能将任意数据散列后映射到有限的空间上,一般计算机软件中用做快速查找或加密使用。web

哈希冲突:因为哈希算法被计算的数据是无限的,而计算后的结果范围有限,所以总会存在不一样的数据通过计算后获得的值相同,这就是哈希冲突。算法

2.解决哈希冲突的方法

解决哈希冲突的方法通常有:开放定址法、链地址法(拉链法)、再哈希法、创建公共溢出区等方法。函数

2.1 开放定址法

从发生冲突的那个单元起,按照必定的次序,从哈希表中找到一个空闲的单元。而后把发生冲突的元素存入到该单元的一种方法。开放定址法须要的表长度要大于等于所须要存放的元素。
在开放定址法中解决冲突的方法有:线行探查法、平方探查法、双散列函数探查法。
开放定址法的缺点在于删除元素的时候不能真的删除,不然会引发查找错误,只能作一个特殊标记。只到有下个元素插入才能真正删除该元素。加密

2.1.1 线行探查法

线行探查法是开放定址法中最简单的冲突处理方法,它从发生冲突的单元起,依次判断下一个单元是否为空,当达到最后一个单元时,再从表首依次判断。直到碰到空闲的单元或者探查彻底部单元为止。
能够参考csdn上flash对该方法的演示:
http://student.zjzk.cn/course_ware/data_structure/web/flash/cz/kfdzh.swfspa

2.1.2 平方探查法

平方探查法便是发生冲突时,用发生冲突的单元d[i], 加上 1²、 2²等。即d[i] + 1²,d[i] + 2², d[i] + 3²...直到找到空闲单元。
在实际操做中,平方探查法不能探查到所有剩余的单元。不过在实际应用中,能探查到一半单元也就能够了。若探查到一半单元仍找不到一个空闲单元,代表此散列表太满,应该从新创建。指针

2.1.3 双散列函数探查法

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

2.2 链地址法(拉链法)

连接地址法的思路是将哈希值相同的元素构成一个同义词的单链表,并将单链表的头指针存放在哈希表的第i个单元中,查找、插入和删除主要在同义词链表中进行。链表法适用于常常进行插入和删除的状况。
以下一组数字,(3二、40、3六、5三、1六、4六、7一、2七、4二、2四、4九、64)哈希表长度为13,哈希函数为H(key)=key%13,则链表法结果以下:get

0       
1  -> 40 -> 27 -> 53 
2
3  -> 16 -> 42
4
5
6  -> 32 -> 71
7  -> 46
8
9
10 -> 36 -> 49
11 -> 24
12 -> 64

注:在java中,连接地址法也是HashMap解决哈希冲突的方法之一,jdk1.7彻底采用单链表来存储同义词,jdk1.8则采用了一种混合模式,对于链表长度大于8的,会转换为红黑树存储。flash

2.3 再哈希法

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

2.4 创建公共溢出区

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

做者:冬天里的懒喵 连接:https://www.jianshu.com/p/4d3cb99d7580 來源:简书 简书著做权归做者全部,任何形式的转载都请联系做者得到受权并注明出处。

相关文章
相关标签/搜索