目录
哈希表
是一种实现关联数组抽象数据类型的数据结构,这种结构可以将关键码映射到给定值。
简单来说哈希表(key-value)之间存在一个映射关系,是键值对的关系,一个键对应一个值
哈希冲突
当两个不同的数经过哈希函数计算后得到了同一个结果,即他们会被映射到哈希表的同一个位置时,即称为发生了哈希冲突。简单来说就是哈希函数算出来的地址被别的元素占用了
解决碰撞方法
1、开放定址法
出现冲突后按照一定算法查找下一个空位置
公式:H(x) = (hash(x) + ) mod m; 其中i=1,2,...m-1
优点:容易系列化
缺点:占用空间大。为减少冲突,要求装填因子d较小,故当结点规模较大时会浪费很多空间,其次不能真正的删除,不能简单的将删除节点位置置空,会影响到其他同义词节点的查找路劲,只能在被删节点上做删除标记。 节点规模大时效率低。
a)、线性探测法
公式:H(x) = (hash(x) + ) mod m; d = 1,2,3...m-1;(d为递增加1)
若哈希函数算出来的位置被占了,则对i一直加知道再次计算出哈希函数值位置不被占用
ThreadLocalMap就是使用该方法
举个栗子:0, 1, 2, 6, 7, 8
值 | hash值 |
0 | h(0) = 0 % 6 = 0 |
1 | h(1) = 1 % 6 = 1 |
2 | h(2) = 2 % 6 = 2 |
6 | h(6) = 6 % 6 = 0 被占用 h(6) = (6 + 1) % 6 = 1 被占用 h(6) = (6 + 2) % 6 = 2 被占用 h(6) = (6 + 3) % 6 = 3 |
7 | h(7) = 7 % 6 = 1 被占用 h(7) = (7 + 1) % 6 = 2 被占用 h(7) = (7 + 2) % 6 = 3 被占用 h(7) = (7 + 3) % 6 = 4 |
8 | h(8) = 8 % 6 = 2 被占用 h(8) = (8 + 1) % 6 = 3 被占用 h(8) = (8 + 2) % 6 = 4 被占用 h(8) = (8 + 3) % 6 = 5 |
a)、二次探测法
又名平方探测法,若计算出的哈希值位置被占了,会前后寻找而不是单独方向的寻找。
公式:H(x) = (hash(x) + ) mod m; (d依次为+(i^2)和-(i^2),i每次递增+1
举个栗子:0, 1, 2,3,5
0 | h(0) = 0 % 5 = 0 |
1 | h(1) = 1 % 5 = 1 |
2 | h(2) = 2 % 5 = 2 |
3 | h(3) = 3 % 5 = 3 |
5 | h(5) = 5 % 5 = 0 被占用 h(5) = (5 + 1^2) % 5 = 1 被占用 h(5) = (5 + (-1^2)) % 5 = 4 |
c)伪随机探测
随机产生一个增量位移
公式:H(x) = (hash(x) + ) mod m; (d为伪随机位数列)
举个栗子:0, 8, 11,伪随机位数列为3,7,11...
0 | h(0) = (0+3) % 3 = 0 |
1 | h(8) = (8+3) % 3 = 2 |
2 | h(11) = (11+3) % 3 = 2 被占用 h(11) = (11+7) % 3 = 0 被占用 h(11) = (11+11) % 3 = 1 |
2、再哈希法
再哈希法,又叫双哈希法,用多个不同的Hash函数,出现冲突后采用其他的哈希函数计算,直到不再冲突为止
优点:不易发生聚集
缺点:增加了计算时间
H(x) = RHash(x) mod length
比如:H(10) = 10 * 3.1415926 * x % 10 使用了多个乘法hash函数
3、拉链法
将具有相同哈希地址的记录链成一个单链表,m个哈希地址就设m个单链表,然后用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构
hashMap就是这个方法
优点:
1、拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;
2、由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;
3、当结点规模较大时,拉链法中增加的指针域可忽略不计,因此节省空间;
4、在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。
缺点:
1、节点规模小时,指针占用较大空间时,相比于其他方法会造成空间浪费
举个栗子:集合{47,7,29,11,16,92,22,8,3,50,37,89},m = 11,
哈希算法为H(k) = k mod 11,则建表如下图
4、建立公共溢出区
创建哈希表时,将所有产生冲突的的同义词集中另外在放在一个溢出表中
举个栗子:
集合{26,36,41,38,44,15,68,12,6,51,25},m = 12,
哈希函数:H(k)= k mod 12,则哈希表如下:
有哈希冲突的,另外都放到溢出表