一、这里就介绍3种常用于解决哈希冲突的方法
开放定址法
就是解决hash冲突的一种方式。它是使用一种 探测方式在整个数组中找到另一个可以存
储值的地方。
链地址法(拉链法)
HashMap,HashSet其实都是采用的拉链法来解决哈希冲突的,就是在每个位桶
实现的时候,我们采用链表(jdk1.8之后采用链表+红黑树)的数据结构来去存取发生哈希冲突的输
入域的关键字
再散列法
再散列法其实很简单,就是再使用哈希函数去散列一个输入的时候,输出是同一个位置就
再次散列,直至不发生冲突位置
缺点:每次冲突都要重新散列,计算时间增加。
二、3种方法的详细说明
-
开放定址法:
- 原理:开放定址法是一种解决冲突的方法,当发生哈希冲突时,通过在哈希表中寻找另一个空闲位置来存储冲突的数据。
- 步骤:根据某种规则,依次探测哈希表中的下一个位置,直到找到一个空闲位置为止。
- 常见的探测方法:
- 线性探测:
按顺序决定哈希值时,如果某数据的哈希值已经存在,则在原来哈希值的基础上往后加一个 单位,直至不发生哈希冲突。
- 二次探测:
按顺序决定哈希值时,如果某数据的哈希值已经存在,则在原来哈希值的基础上先加1的平方 个单位,若仍然存在则减1的平方个单位。随之是2的平方,3的平方等等。直至不发生哈希冲突。
- 双重散列:
按顺序决定哈希值时,如果某数据已经存在,通过随机函数随机生成一个数,在原来哈希值 的基础上加上随机数,直至不发生哈希冲突
- 线性探测:
- 优点:简单、易于实现。
- 缺点:容易产生聚集,可能导致性能下降。
-
链地址法(拉链法):
- 原理:链地址法是一种解决冲突的方法,将哈希表中每个位置都连接一个链表,冲突的数据存储在链表中。
- 步骤:当发生冲突时,将数据插入到对应位置的链表中。
- 优点:容易实现,适用于存储大量数据。
- 缺点:需要额外的空间存储链表指针,可能造成内存浪费。
-
再散列法:
- 原理:再散列法是一种解决冲突的方法,当发生哈希冲突时,通过对冲突的键应用另一个哈希函数来寻找另一个空闲位置存储数据。
- 步骤:选择合适的再散列函数,根据冲突的键生成新的哈希码,寻找空闲位置存储数据。
- 优点:能够有效地减少冲突,提高哈希表的性能。
- 缺点:需要选择合适的再散列函数,可能会影响数据的分布均匀性。
三、 开放寻址法和拉链法的优缺点
1.开放定址法:容易产生堆积问题;不适于大规模的数据存储;
散列函数的设计对冲突会有很大
的影响
;插入时
可能会出现多次冲突的现象
,删除的元素是多个冲突元素中的一个,需要对后面的
元素作处理,实现较复杂;
结点规模很大时会浪费很多空间(再平方探测 )
;
2.链地址法:处理冲突简单,且无堆积现象,平均查找长度短;链表中的结点是动态申请的,适合构造表不能确定长度的情况;相对而言,拉链法的指针域可以忽略不计,因此较开放地址法更加节省空间。插入结点应该在链尾部(jdk1.8),删除结点比较方便,只需调整指针而不需要对其他冲突元素作调整。