【散列表】散列表的概念,散列函数设计和散列冲突和解决方案

散列表(Hash Table) 也称哈希表

散列表用的是数组支持按照下标随机访问数据的特性,所以散列表是数组的扩展

将key通过散列函数将key转化映射为散列值,便是数组下标

散列函数设计的基本要求:

1.散列函数计算得到的散列值是一个非负整数

2.如果key1 = key2,那hash(key1) == hash(key2)

3.如果key1 ≠ key2,那hash(key1)≠hash(key2)

第三点在真实情况下,要想找到一个不同的key对应的散列值都不一样的散列函数,几乎是不可能的。即便像MD5、SHA、CRC等哈希算法,也无法完全避免这种散列冲突

散列冲突的解决

再好的散列函数也无法避免散列冲突,该如何解决这种冲突:

1.开放寻址法

如果出现了散列冲突,则重新探测一个空闲位置,将其插入。那如何探测呢?

线性探测:

当我们往散列表中插入数据时,如果某个数据经过散列函数散列后,存储位置已经被占用了,就从当前位置开始,依次往后查找,看是否有空闲位置,直到找到为止

在散列表中查找元素的过程有点类似插入。通过散列函数求出要查找元素的键值对应的散列值,然后比较数组中下标为散列值的元素和要查找的元素。如果遍历到数组中的空闲为止,还没有找到,就说明要查找的元素并没有在散列表中

删除的元素要特殊标记为deleted,否则会造成查找算法失效。当线性探测查找的时候遇到标记则继续往下探测

随着插入的数据越来越多,空闲位置越来越少,散列冲突发生的可能性越来越大,线性探测的时间会越来越久,极端情况下,可能要探测整个散列表,最坏情况下时间复杂度O(n)

二次探测

线性探测的步长是1,二次探测的步长变成了原本的二次方

双重散列

不仅要使用一个散列函数,要使用一组散列函数

先用第一个散列函数,如果计算得到的存储位置已经被占用,再用第二个散列函数,以此类推

装载因子:表示空位的多少

散列表的装载因子 = 填入表中的元素个数 / 散列表的长度

装载因子越大,说明空闲位置越少,冲突越多,散列表的性能会下降

2.链表法

在散列表中,每个槽会对应一条链表,所以散列值相同的元素都放到相同的槽位对应的链表中

插入的时间复杂度O(1),查询和删除的时间复杂度跟链表的长度k成正比O(k)

k=散列中数据的个数 / 散列表中槽的个数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值