hash冲突
- 当做hash计算时 A与B计算出来的值都是C,这就发生了hash冲突。
- 解决的办法如下
- 开放定址法
keyA=hash(A);出现冲突时,我们以keyA为基础再进行hash计算,
例如:keyA1 = hash(A+keyA);公式定义如下
为产生冲突的key获取一个地址序列
这里的m,是表的长度tablesize
怎么理解呢,就是在原有的hash值基础上增加一个值di再进行取模,避免与之前的key出现冲突,
其中 di有几种取值方式。
1.线性探索即累计+1的方式{1,2,3,4…m-1}
2.平方探索
平方探测因为是平方探测,因此出现冲突的概率依然很高,
- 再hash算法是重新建立一个hash函数,计算hash值
- 公共溢出区 就是将hash表分为两个表一个存正常hash的值,另一个表存储发生冲突的值。
不过开放定址法这种方式在位置都被占的情况下就没有办法了。因为不论怎么探索,都会hash冲突。怎么办?
于是就有了拉链法了
拉链是啥?
看图
大概结构就是这个样子,hash表位置冲突后,不是重新定址,而是直接冲突值存到这个位置,例如图中1的位置冲突的value为31,21,11。此时1的位置存储的是一个指针指向最先存入的value位置,以此类推,没次冲突时将新的值添加下一个节点。
此方法有啥好处?
1 上面说了为了解决多次hash冲突,而且删除节点时也方便了。
2 节点删除也更容易了
3 查询时间缩短(因为不用重新定址,一步就能定位到具体位置,在根据位置查询数据)
缺点呢?
如果有一个人点碰撞值,会导致一条很长的链表出现,因为单链表,检索需要一个个查找
所以在jdk1.8以后hashmap替换了链表,使用了红黑树。
触发链表转红黑树的负载因子是8(同一个hash表位置冲突值满8个也不容易)
删除节点时,红黑树转成链表的因子数是6