解决哈希冲突的方式有哪些?

233 阅读3分钟

文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。

相信很多人都听说过哈希冲突这个词,那么当发生哈希冲突的时候,我们可以是用什么方法进行解决呢?HashMap是如何解决的呢?

下面提供一个数据结构与算法的学习网站,觉得有用的大家帮忙点个赞!!!

推荐一个数据结构学习网站: www.cs.usfca.edu/~galles/vis…

一、简绍

在前文我先给出两种常用的解决方式,后面我们逐个进行分析,看看到底是怎么个意思:

冲突解决技术可以分为两类:
1)Open Hashing开散列方法, 又叫拉链法
2)Closed Hashing闭散列方法, 又叫开地址法 (Open Addressing)

以上两种方法有着最直接的区别,通过名称就能联想到:
开散列法把发生冲突的关键码存储在散列表主表之外;
闭散列法把发生冲突的关键码存储在表中另一个槽内。

二、Open Hashing开散列法(拉链法)

开散列方法的一种简单形式是把散列表中的每个槽定义为一个链表的表头。散列到一个特定槽的所有记录都放到这个槽的链表中。

下面通过一个例子具体看下:

有一个13个槽的哈希散列,如下所示:

image.png

通过key%哈希表长度取余,找到放置key的位置。例如放置30,则30%13 = 4

image.png

添加相同hash值的key时,放入一个82,结果如下图

image.png 发现存在相同key的hash值时,在数组的该槽位上生成了一个单向链表,用于解除哈希冲突问题。

当我们有很多个相同的hash值时,这个链会越来越长,所以又称为拉链法。Hashmap在jdk1.7时就是使用的这种方式,在jdk1.8时,增加红黑树,此处不再引申。

三、closed Hashing闭散列发

闭散列方法, 又叫开地址法,当发生哈希冲突时,如果该哈希表还没有被填满,那么就把该元素放到哈希表的下一个空闲的位置。

举个例子:
长度为29的哈希表:

image.png

通过key%哈希表长度取余,找到放置key的位置。例如放置30,则30%29 = 1。

image.png

再次放置一个余1的key,放置59,59%29 = 1。

image.png

发现相同哈希值的key被放在了下一个空闲的位置。

闭散列方式又叫做开地址法。

四、使用桶的闭散列法(Closed Hashing,Using Buckets)

在上面的闭散列方式基础之上,引入了桶的概念,相当于变相增加了容量。因为直接使用闭散列的方式很容易将整个哈希散列装满。

通过下图我们来看下桶是如何使用的,如下图,分割了11个桶,每个桶内部又分出三个位置,用于存储相同的key的hash值,当三个存满后会将溢出值放入最后的overflow溢出区。

image.png

连续存入4个哈希值是1的不同值12,23,34,45,分别取余都得到1,则会存入三个在1区,最后一个放在溢出区

image.png

本文简单介绍到这,兄弟们有学到帮忙点个赞。