拉勾教育 重学数据结构与算法 10 | 哈希表:如何利用好高效率查找的“利器”?

学习资源:拉勾教育

哈希表的核心思想

  • 哈希表的设计采用了函数映射的思想,将记录的存储位置与记录的关键字管理起来,这样的设计方式,能够快速定位到想要查找的记录,而且不需要与表中存在的记录的关键字比较后再来进行查找
  • 如果有一种方法,可以实现“地址=f(关键字)”的映射关系,那么就可以快速完成基于数据的数值的查找了,这就是哈希表的核心思想
  • 哈希表需要设计合理的哈希函数,并且对冲突有一套处理机制

如何设计哈希函数

  1. 直接定制法:哈希函数为关键字到地址的线性函数。如,H(key) = a * key + b,这里a和b是设置好的常数
  2. 数字分析法:假设关键字集合中的每个关键字key都是由s位数字组成(k1,k2,…,ks)并从中提取分布均匀的若干位组成哈希地址
  3. 平方取中法:如果关键字的每一位都有某些数字重复出现,并且频率很高,可以先求关键字的平方值,通过平方扩大差异,然后取中间几位作为最终存储地址
  4. 折叠法:如果关键字的位数很多,可以将关键字分割为几个等长的部分,取它们的叠加和的值(舍去进位)作为哈希地址
  5. 除留余数法:预先设置一个数p,然后对关键字进行取余运算,即地址为key mod p

如何解决哈希冲突

  • 开放地址法:当一个关键字和另一个关键字发生冲突时,使用某种探测技术在哈希表中形成一个探测序列,然后沿着这个探测序列依次查找下去,当碰到一个空的单元时,则插入其中,常用的探测方法是线性探测法
    在这里插入图片描述
  • 链地址法:将哈希表相同的记录存储在一张线性表中
    在这里插入图片描述

哈希表的优劣势

  • 哈希表的优势:它以提供非常快速的插入-删除-查找操作,无论多少数据,插入和删除值需要接近常量的时间。在查找方面,哈希表的速度比树还要快,基本可以瞬间查找到想要的元素
  • 哈希表的不足:哈希表中的数据没有顺序概念的,所以不能以一种固定的方式(比如从小到大)来遍历其中的元素,哈希表中的key是不允许重复的

哈希表的基本操作

  • 哈希表完成了关键字到地址的映射,可以在常熟级时间复杂度内通过关键字查找到数据
  • 哈希表中的增加和删除数据操作,不涉及增删后对数据的挪移问题
  • 哈希表查找的细节过程是:对于给定的key,通过哈希函数计算哈希地址H(key),如果哈希地址对应的值为空,则查找不成功,反之则查找成功

哈希表的案例——存储关键字序列

将关键字序列{7,8,30,11,18,9,14}存储到哈希表中,哈希函数为:H(key) = (key * 3) % 7,处理冲突采用线性探测法
在这里插入图片描述
查找的流程:

  • 查找7,输入7,计算得到H(7) = 0,
    • 根据哈希表,在0的位置,得到结果为7,跟待匹配的关键字一样,则完成查找。
  • 查找18,输入18,计算得到H(18) = 5
    • 根据哈希表,在5的位置,得到的结果为11,跟待匹配的关键字不一样
    • 往后挪移一位,在6的位置,得到的结果为30,跟待匹配的关键字不一样
    • 往后挪移一位,在7的位置,得到的结果为18,跟待匹配的关键字一样,完成查找

哈希表的案例——记录关键字被提交的次数

假设有一个在线系统,可以实时接收用户提交的字符串型关键字,并实时返回给用户累计至今这个关键字被提交的次数。例如,用户输入"abc",系统返回1;用户再输入“jk”,系统返回1;用户再输入“xyz”,系统返回1;用户再输入“abc”,系统返回2;用户再输入“abc”,系统返回3。
如果采用哈希表,则可以利用哈希表新增、查找的常数级时间复杂度,在O(1)时间复杂度内完成相应,预先定义好哈希表后,可以采用Map<String,Integer> d = new HashMap<>();

if(d.containsKey(key_str)) {
    d.put(key_str, d.get(key_str) + 1);
} else {
    d.put(key_str, 1);
}
System.out.println(d.get(key_str));

总结

  • 利用哈希表查找、插入、删除只需要接近常量的时间,即O(1)的时间级
  • 如果需要在一秒钟内查找上千条记录通常使用哈希表
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值