Java数据结构——哈希表

哈希表基于数组,类似于key-value的存储形式,关键字值通过哈希函数映射为数组的下标,如果一个关键字哈希化到已占用的数组单元,这种情况称为冲突。用来解决冲突的有两种方法:开放地址法和链地址法。在开发地址法中,把冲突的数据项放在数组的其它位置;在链地址法中,每个单元都包含一个链表,把所有映射到同一数组下标的数据项都插入到这个链表中。

参考博客 : https://www.cnblogs.com/ysocean/p/8032656.html 。 文章不足之处,欢迎评论

引言
如果我们有10个单词,怎样做到快速存取呢?有一个很快的方法就是将这10个单词放入数组中,通过数组下标进行存取。

提出问题
但是问题来了,10个单词还比较好解决,成千上万的单词呢?我们假设有5000个单词,那么放到一个容量是5000的数组中,我们要查找某个单词,需要知道它的下标,那么下标怎么知道?这样就又回到了遍历查找了。。。。

原因
那么我们缺少了什么?缺少的就是如何建立单词和下标的联系(下标和单词的联系已经有了,因为知道下标肯定能知道单词。但是知道单词不一定知道下标Orz。。。)。

尝试方法1(摒弃)
那么我们怎么建立单词和下标的联系呢?首先我们可以通过一些简单的定义加公式来建立一些联系,如定义a为1,b为2…z为26。然后单词cat就等于3+1+20 = 24了,所有的单词遵循这样的规则就能找到自己对应的下标了。
=》这个尝试解决了单词和下标的联系问题,但是想一下,数字的重复还是很严重的。

方法一:考虑每个数组项包含一个子数组或者一个子链表,这个办法存数据项确实很快,但是如果我们想要从子数组中查找到其中一个,那么还是很慢。

方法二:为啥要让那么多单词占据同一个数据项呢?也就是说我们没有把单词分的足够开,数组能表示的元素太少,我们需要扩展数组的下标,使其每个位置都只存放一个单词。

基于上面的方法二,提出解决方法2.

尝试方法2(还有重复问题需要解决)
我们可以将数字放大,通过类似如下的幂的连乘:
cat = 3273 + 1272 + 20*271 = 59049 + 729 + 540 = 60318,这个过程会为每个单词创建一个独一无二的数,但是注意的是我们这里只是计算了 4 个字母组成的单词,如果单词很长,比如最长的10个字母的单词 zzzzzzzzzz,仅仅是279 结果就超出了7000000000000,这个结果是很巨大的,在实际内存中,根本不可能为一个数组分配这么大的空间。
我们要把一群很大的数字,压缩到一个很小的范围可以采用取余的方式,假设要把从0-199的数字(用largeNumber表示),压缩为从0-9的数字(用smallNumber表示),后者有10个数,所以变量smallRange 的值为10,这个转换的表达式为:
  smallNumber = largeNumber % smallRange
这也就是哈希函数。它把一个大范围的数字哈希(转化)成一个小范围的数字,这个小范围的数对应着数组的下标。使用哈希函数向数组插入数据后,这个数组就是哈希表

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值