哈希表是如何实现的,如何解决哈希冲突

首先我们要知道的是哈希表是怎么实现的,哈希表(Hash table)的原理就是把key通过一个固定的算法函数(哈希函数)转化为一个整形数字,然后对其进行数组长度进行取余,取余结果作为数组下标,并将 value 存储在该数组空间中。
Hash 算法就是把任意长度的输入通过散列算法变成一个固定长度的输出,这个输出结果就是一个散列值所以 Hash 表也被称为“散列表”。那么知道这些以后,我们要思考的是,哈希冲突是什么,如何产生的哈希冲突以及我们如何去处理哈希冲突,别着急,一个点一个点的揭开面纱。
哈希冲突是因为哈希算法被计算的数据是无限的,但是我们计算后的结果范围有限,因此总会存在不同的数据,经过计算后得到的值是一样的,这样可能导致不同的输入值映射到同一哈希值。这就是我们说的哈希冲突问题,那么如何去解决哈希冲突呢,通常用以下这些方法:

  1. 开放地址法(open Addressing):这种方法的思想就是当我们的key的哈希地址出现冲突时(以p为基准),产生另外一个哈希地址p1,如果p1仍然冲突则再以p为基准产生一个p2,直到找出一个不冲突的哈希地址pi,其中常见的比如有线性探查、二次探查以及双重哈希。
  2. 链地址法(Separate Chaining):这种方法的基本思想就是将哈希表的每一个位置看作一个桶,当新的元素哈希值冲突时,将它添加到同一哈希值当其他元素的链表中。即将所有的哈希地址相同的元素i构成一个单链表,并将单链表的头指针存在哈希表的第i个单元中。这个方法可以适用于经常进行插入和删除的情况。
  3. 再哈希法(Rehashing):在哈希冲突时,使用另一种哈希函数进行哈希,直到找到空闲的槽为止。但是请注意这种方法会增加计算的一个时间,性能上会有一定影响。
  4. 公共溢出区(Public Overflow Area):建立公共溢出区,将哈希表分为公共表和溢出表,当溢出发生时,将所有溢出数据统一放到溢出区。使用这种方法,凡是和基本表发生冲突的都会被填入溢出表,比较粗暴。

针对第一个点中提到的线性探查和二次探查以及双重哈希,在此做具体解释:
线性探测是开放地址法的一种具体体现,当哈希冲突发生时,线性探测会挨个检查哈希表中的下一个位置直至有一个空位,这种方法简单直接,但是可能有时候会导致数据分别不均,查找效率不高,这种情况也有一个专有名词叫做聚类,那么为了避免这个情况,还可以考虑二次探查以及双重哈希。二次探查是指通过前后跳跃方式去探测,比如当冲突发生时,向前探测两位,向后探测五位,向前探测五位·····以一个跳跃式的方式去探测,可以有效避免堆积。双重哈希是通过使用两个不同的哈希函数来减少冲突概率,当冲突发生时,双重哈希会尝试第二个哈希函数去寻找一个空槽位,这个方法优点在于比较简单,并且通常可以有效解决冲突,但是要选择合适的两个哈希函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张恨水水水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值