2022-07-05 数据结构与算法-散列表、哈希算法

散列表

散列表⽤的是数组⽀持按照下标随机访问数据的特性,所以散列表其 实就是数组的⼀种扩展,由数组演化⽽来。可以说,如果没有数组,就没有散列表。

组成

散列函数

Hash(key)

  1. 直接定址法:Hash(key)=a*key+b (a、b为常数)
  2. 数字分析法
  3. 平方取中法
  4. 折叠法
  5. 除留余数法:Hash(key)=key mod p (p是一个整数(最好是小于等于表长的质数))
  6. 随机数法

散列冲突

  • 开放定址法(Open addressing)
    • 线性探测法:一旦冲突,就找下一个地址,直到找到空地址存入,增量序列为1,2,3,4…
    • 二次探测法:一旦冲突,就找下一个地址,直到找到空地址存入,增量序列为12,-12,22,-22…,q2
    • 伪随机探测法:一旦冲突,就找下一个地址,直到找到空地址存入,增量序列为伪随机数

数据量比较小、装载因子小的时候,适合采用开放定址法

  • 拉链法(chaining) 相同散列地址的记录链成一个单链表

基于链表的散列冲突处理⽅法⽐较适合存储⼤对 象、⼤数据量的散列表,⽽且,⽐起开放寻址法,它更加灵活,⽀持 更多的优化策略,⽐如⽤红⿊树代替链表

⼯业级散列表举例因素分析

  1. 初始⼤⼩
  2. 装载因⼦和动态扩容
  3. 散列冲突解决⽅法
  4. 散列函数

应用实例

LRU缓存淘汰算法

需要的操作:

  • 往缓存中添加⼀个数据;
  • 从缓存中删除⼀个数据;
  • 在缓存中查找⼀个数据。

解决方案:

  • LinkedHashMap,在散列的基础上,增加添加元素有序

Redis有序集合

需要的操作:

  • 添加⼀个成员对象;
  • 按照键值来删除⼀个成员对象;
  • 按照键值来查找⼀个成员对象;
  • 按照分值区间查找数据,⽐如查找积分在[100, 356]之间的成员 对象;
  • 按照分值从⼩到⼤排序成员变量;

解决方案:

  • 散列+跳表

LinkedHashMap

LinkedHashMap是通过双向链表和 散列表这两种数据结构组合实现的。LinkedHashMap中 的“Linked”实际上是指的是双向链表,并⾮指⽤链表法解决散列冲突

哈希算法

将任意⻓度的⼆进制值串映射为固定⻓度的⼆进制值串,这个映射的规则就是哈希算法,⽽通过原始数据映射之后得到的⼆进制值串就是哈希值

需要满足的条件

  • 从哈希值不能反向推导出原始数据(所以哈希算法也叫单向哈希 算法);
  • 对输⼊数据⾮常敏感,哪怕原始数据只修改了⼀个Bit,最后得到 的哈希值也⼤不相同;
  • 散列冲突的概率要很⼩,对于不同的原始数据,哈希值相同的概 率⾮常⼩;
  • 哈希算法的执⾏效率要尽量⾼效,针对较⻓的⽂本,也能快速地 计算出哈希值。

应用

安全加密

  1. MD5(MD5 Message-Digest Algorithm,MD5消息 摘要算法)
  2. SHA(Secure Hash Algorithm,安全散列算法)
  3. DES(Data Encryption Standard,数据加密标准)
  4. AES(Advanced Encryption Standard,⾼级加密标准)

发生脱库解决方案:

  • 主要为了增加破解难度
  • 要维护⼀个常⽤密码的字典表,把字典中的每个密码⽤哈 希算法计算哈希值,然后拿哈希值跟脱库后的密⽂⽐对
  • 引⼊⼀个盐(salt),跟⽤户的密码组合在⼀ 起,增加密码的复杂度

唯一标识

获取数据固定片段(如前100、中100、后100字节)进行哈希算法,根据哈希值再进行判断可以节省大量计算。

数据校验

基于P2P协议文件下载,将一个文件分为多个文件块,可以对每个文件块进行哈希算法,保证数据安全。

散列函数

保证哈希冲突小,出现冲突时,使用开放定址法、拉链法解决冲突。

负载均衡

保证会话粘滞(Session sticky),需要在同⼀个客户端上,在⼀次会话中的所有请求都 路由到同⼀个服务器上。

可以通过 哈希算法,对客户端IP地址或者会话ID计算哈希值,将取得的哈希值 与服务器列表的⼤⼩进⾏取模运算,最终得到的值就是应该被路由到 的服务器编号。

数据分片

两个例子

  1. 如何统计“搜索关键词”出现的次数?

以先对数据进⾏分⽚,然后采⽤多台机器处 理的⽅法,来提⾼处理速度;

为了提⾼处理的速 度,我们⽤n台机器并⾏处理。我们从搜索记录的⽇志⽂件中,依次读 出每个搜索关键词,并且通过哈希函数计算哈希值,然后再跟n取模, 最终得到的值,就是应该被分配到的机器编号。

  1. 如何快速判断图⽚是否在图库中?

同样可以对数据进⾏分⽚,然后采⽤多机处理。我们准备n台机 器,让每台机器只维护某⼀部分图⽚对应的散列表。我们每次从图库 中读取⼀个图⽚,计算唯⼀标识,然后与机器个数n求余取模,得到的 值就对应要分配的机器编号,然后将这个图⽚的唯⼀标识和图⽚路径 发往对应的机器构建散列表;

当要判断⼀个图⽚是否在图库中的时候,我们通过同样的哈希算 法,计算这个图⽚的唯⼀标识,然后与机器个数n求余取模。假设得到 的值是k,那就去编号k的机器构建的散列表中查找。

分布式存储

问题原因:

  • 但是,如果数据增多,原来的10个机器已经⽆法承受了,我们就需要 扩容了,⽐如扩到11个机器,这时候⿇烦就来了;

  • 原来的数据是通过与10来取模的。⽐如13这个数据,存储在编号为3 这台机器上。但是新加了⼀台机器中,我们对数据按照11取模,原来13这个数据就被分配到2号这台机器上了。

解决方案:⼀致性哈希算法

  • 假设有k个机器,数据的哈希值的范围是[0, MAX]。我们将整个范 围划分成m个⼩区间(m远⼤于k),每个机器负责m/k个⼩区间。当 有新机器加⼊的时候,就将某⼏个⼩区间的数据,从原来的机器 中搬移到新的机器中。这样,既不⽤全部重新哈希、搬移数据,也保持了各个机器上数据数量的均衡;
  • ⼀致性哈希算法的基本思想就是这么简单。除此之外,它还会借助⼀ 个虚拟的环和虚拟结点,更加优美地实现出来;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值