哈希冲突(散列冲突)的解决方案

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lycyl/article/details/72637332

哈希冲突

    哈希表底层是链表的数组实现的,如果通过哈希算法散列key之后,发现要添加新元素的位置已经有别的元素占有了,并且二者的key值不相等,这就是哈希冲突现象。

解决哈希冲突的方案有开放地址法、链表法、再哈希法和建立一个公共溢出区。


开放地址法

    就是在发生冲突后,通过某种探测技术,去依次探查其他单元,直到探查到不冲突为止,将元素添加进去。

假如是在index的位置发生哈希冲突,那么通常有一下几种探测方式:


线性探测法

    向后依次探测index+1,index+2...位置,看是否冲突,直到不冲突为止,将元素添加进去。


扫描二维码关注公众号,回复: 5534780 查看本文章

平方探测法

    不探测index的后一个位置,而是探测2^i位置,比如探测2^0位置上时发生冲突,接着探测2^1位置,依此类推,直至冲突解决。


两种探测法的优缺点

    线性探测法虽然在哈希表未满的情况下,总能保证找到不冲突的地址,但是容易发生二次哈希冲突的现象。比如在处理若干次次哈希冲突后k,k+1,k+2位置上的都存储了数据,那下一次存储地址在k,k+1,k+2,k+3位置的数据都将存在k+3位置上,这就产生了二次冲突。

    这里引入一个新的概念,堆积现象是指用线性探测法处理哈希冲突时,k,k+1,k+2位置已存有数据,下一个数据请求地址如果是k,k+1,k+2,k+3的话,那么这四个数据都会要求填入k+3的位置。


    平方探测法可以减少堆积现象的发生,但是前提是哈希表的总容量要是素数4n+3才可以。


再哈希法

    在发生哈希冲突后,使用另外一个哈希算法产生一个新的地址,直到不发生冲突为止。这个应该很好理解。

    再哈希法可以有效的避免堆积现象,但是缺点是不能增加了计算时间和哈希算法的数量,而且不能保证在哈希表未满的情况下,总能找到不冲突的地址。


链表法

    链表法就是在发生冲突的地址处,挂一个单向链表,然后所有在该位置冲突的数据,都插入这个链表中。插入数据的方式有多种,可以从链表的尾部向头部依次插入数据,也可以从头部向尾部依次插入数据,也可以依据某种规则在链表的中间插入数据,总之保证链表中的数据的有序性。Java的HashMap类就是采取链表法的处理方案。


建立一个公共溢出区

    建立一个基本表,基本表的大小等于哈希表的大小。建立一个溢出表,所有哈希地址的第一个记录都存在基本表中,所有发生冲突的数据,不管哈希算法得到的地址是什么,都放入溢出表中。

    但是有一个缺点就是,必须事先知道哈希表的可能大小,而且溢出表里的数据不能太多,否则影响溢出表的查询效率。实际上就是要尽量减少冲突。


结束语

    哈希表一旦发生冲突,其性能就会显著下降。因此建立哈希表时必须规避哈希冲突的产生,大多数哈希表的实现都是:第一步,时通过哈希算法将key值转换一个整数以确定数据的存储位置;第二步,检查是否发生哈希冲突,以及确定发生冲突后的处理方案。


猜你喜欢

转载自blog.csdn.net/lycyl/article/details/72637332
今日推荐