Java数据结构:散列表

1、散列函数

将任意长度的二进制值串映射为固定长度的二进制值串,这个映射的规则就是哈希算法。如MD5,就是一种被广泛使用的密码散列函数。

MD5(12)=C20AD4D76FE97759AA27A0C99BFF6710  

MD5(123)=202CB962AC59075B964B07152D234B70

2、散列表


散列表(Hash table,也叫哈希表),就是通过散列函数将关键码值(key值)映射到数组中一个位置,该位置用于存储key对应的value,存放记录的数组叫做散列表。

可以通过key的散列函数,快速定位到数据的位置,取出value值。时间复杂度O(1)(hasn不冲突的情况)

3、为什么散列函数无法做到零冲突?

比如上面 MD5 的例子,哈希值是固定的 128 位二进制串,能表示的数据是有限的,最多能表示 2^128 个数据,而我们要哈希的key是无穷的。基于鸽巢原理,如果我们对 2^128+1 个数据求哈希值,就必然会存在哈希值相同的情况。所以哈希值越长的哈希算法,散列冲突的概率越低。

3、散列函数设计考虑的因素:

(1)基于数据安全性考虑,从哈希值不能反向推导出原始数据

(2)对输入数据非常敏感,哪怕原始数据只修改了一个 Bit位,最后得到的哈希值也大不相同;

(3)散列冲突的概率要很小,对于不同的原始数据,哈希值相同的概率非常小;

(4)哈希算法的执行效率要尽量高效,针对较长的文本,也能快速地计算出哈希值。

4、前人总结的比较优秀的hash函数的构造方式:

(1)直接定址法:取关键字的某个线性函数值为散列地址 f(key) = a × key + b

(2)除留余数法 (用的较多) :f( key ) = key mod p ( p ≤ m )。mod是取模(求余数)的意思。事实上,这方法不仅可以对关键字直接取模,也可在折叠、平方取中后再取模。

(3)平方取中法

(4)折叠法:将关键字拆分成几部分,然后将这几部分组合在一起,以特定的方式进行转化形成Hash地址。假如知道图书的ISBN号为8903-241-23,可以将Hash(key)=89+03+24+12+3作为Hash地址

(5)数字分析法

(6)随机数法

(7)time33算法(PHP的数组就是把这个作为哈希函数)

以上hash函数感兴趣可以查询相关资料,了解其原理

5、散列函数的应用:

(1)安全加密:最常用于加密的哈希算法是MD5和SHA、DES、AES;利用散列函数散列值不能反向推导出原始数据的特性

(2)唯一标识:如海量图片中判断某张图片是否存在、数据库主键等应用

(3)负载均衡:

对客户端 IP 地址或者会话 ID 计算哈希值,将取得的哈希值与服务器列表的大小进行取模运算,最终得到的值就是应该被路由到的服务器编号。 这样,我们就可以把同一个 IP 过来的所有请求,都路由到同一个后端服务器上。

(4)分布式存储:数据根据哈希函数映射到某台机器上存储

6、散列表的应用:

工业级的散列表:HashMap

Redis的数据类型Hash,底层就是散列表

Redis的数据类型Set,内部实现是一个value永远为null的散列表

Redis的数据类型Sorted Set(有序集合),底层编码实现ziplist和skiplist,skiplist底层就是跳跃链表+hash表

6、哈希表中哈希冲突解决方式:

(1)探测法

当key1和key2的hash值发生冲突时,使用某种探测技术在Hash表中形成一个探测序列,然后沿着这个探测序列依次查找下去,当碰到一个空的单元时,则插入其中。

探测技术有线性探测、二次探测、随机探测

这里以线性探测为例:

 

(2)再哈希法,同时构造多个不同的哈希函数,若对于k1和k2的hash函数的值相同,则为hash冲突,这是再用hash2函数计算k2的hash值,放入哈希表中。这种方式增加了计算时间

(2)链地址法

7、hash表的性能

查找或者插入的情况在大多数情况下可以达到O(1),因为可以通过key的hasn函数,直接定位到数据存放位置。所以操作的时间主要花在计算hash上。

最坏的情况就是hash值全都映射到同一个地址上,这样哈希表就会退化成链表,查找的时间复杂度变成O(n)。这种情况有人蓄意攻击,需要了解基于哈希冲突的拒绝服务攻击。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值