Hash

试想这样的场景,你很想学太极拳,听说学校有个叫张三的人打得特别好,于是你到学校学生处找人,学生处的工作人员可能会拿出学生名单,一个一个地查找,最终告诉你,学校没这个人,并说张三几百年前就已经在武当山作古了。可如果你找对了人,比如在操场上找那些爱运动的同学,人家会告诉你,"哦,你找张三呀,有有有,我带你去。“于是他把你带到了体育馆内,并告诉你,那个教大家打太极的小伙子就是张三,原来"张三丰”是因为他太极拳打得好而得到的外号。

学生处的老师找张三丰,那就是顺序表查找,依赖的是姓名关键字的比较。而询问爱好运动的同学时,没有遍历,没有比较,就凭他们"欲找太极’张三丰’,必在体育馆当中"的经验,直接告诉你位置。

从某种程度上来讲,这种通过关键值来直接查找数据的思想,就是散列。

一、必备知识

1. 算法简介

哈希(Hash)也称为散列,就是把任意长度的输入,通过散列算法,变换成固定长度的输出,这个输出值就是散列值。

哈希表(Hash table,也叫散列表)是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

哈希表的做法其实很简单,就是把Key通过一个固定的算法函数,即所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。

而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位。

2. 算法特征

简单来说,哈希的本质就是映射,可以将数据映射为固定长度的串。

一个好的 Hash 函数应该具备以下特征:

  1. 一致性 —— 同样的key必然会产生相等的hash code。

  2. 高效性 —— 高效的计算,省时省力。

省时——使用O(1)的时间进行数据的插入、删除和查找,但是 hash 表不保证表中数据的有序性,因此,在 hash 表中查找最大数据或者最小数据的时间是 O(N) 。

省空间——与时间复杂度同样是O(1)的桶相比,桶数组中是有很多桶是没有用到的,也就浪费了空间。比如说现在有4个数 (2 4 7 10001) ,如果用桶存储,就必须开一个长度为10001的数组,而用 Hash 则只需开一个长度为 4 的数组即可,它们的位置分别为2 % 4 = 2,4 % 4 = 0,7 % 4 = 3,10001 % 4 = 1

在 Hash 表中表示为

index 0 1 2 3
4 10001 2 7
  1. 均匀性 —— 相对均匀地散列所有的key。

  2. 单向性 —— 对于给定的散列值,很难计算出它的原始输入。

  3. 抗碰撞性 —— 能够有效处理不同的关键字得到同一存储位置的情况(即解决冲突)。

举个大神说过的例子

小星与阿呆聊天中

阿呆:小星,今天来我家玩吗?路上有一家披萨店,很好吃,顺便带点来呗。

小星:哦,要不你来我家玩吧,你顺便带上披萨。

阿呆:既然你都这么说了,看来只能抛硬币解决了。

小星:嗯?这个怎么抛,我怎么知道你有没有搞鬼。

阿呆:嗯,也是。要不这样,我心中想一个数,假设为A,然后A在乘以一个数B,得到结果C。A是我的密钥,我把结果C告诉你。你来猜A是奇数还是偶数,猜中了,就算你赢。

小星:这不行,如果你告诉我C是12,我猜A是奇数,你可以说A是4,B是3。我猜A是偶数,你可以说A是3,B是4。要不你告诉我C是多少的时候,也告诉我B是多少。

阿呆:那这不行,告诉你C和B,不等于告诉你A是多少了,还猜啥呀,我们换个方式。

阿呆:要不这样,我想一个A,经过下面的过程:

  1. A+123=B
  2. B^2=C
  3. 取C的第2~4位数,组成一个3位数D
  4. D%12得到E

阿呆:我把E和上述计算方式都告诉你,你猜A是奇数还是偶数,然后我告诉你A是多少,你可以按上述的计算过程来验证我有没有说谎。

小星:嗯,我想想,假如阿呆你想的A为5,那么:

5 + 123 = 128 --> 128 ^ 2 = 16384 --> D = 638 --> E = 638 % 12 = 53

小星:这样的话,一个A值对应一个唯一的E值,根据E还推算不出来A。优秀!这个还算公平,谁撒谎都能看出来。

这种丢掉一部分信息的加密方式称为“单向加密”,也叫哈希算法。

3. 建立Hash表

在建立一个哈希表之前需要解决两个问题:

1> 构造均匀的哈希函数

常见的构造哈希函数的方法有:

  1. 直接寻址法(常用)。取关键字或关键字的某个线性函数值为散列地址。即H(key)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值