Hash的真面目

简介:

Hash,又叫散列杂凑,音译为哈希Hash函数能够将任意长度的输入压缩成固定长度的输出,且该输出就叫做散列值。由于输出长度是固定的,那输出空间就是有限的,避免不了的会产生重复这种重复也叫冲突、碰撞),而在Hash中重复是不被允许,这会使Hash失去优势。

特点:

​ 众所周知,在数据结构的顺序表中,有数组链表两位老哥,这两位哥互补了对方的优缺点,数组能够实现相当快的数据访问,而链表拥有比数组快的增删数据的能力。Hash集两家之所长,完成了优势融合,能够快速的访问增删数据。

实现方法:

​ 如聪明的你所知,Hash的内部采用键值对的方式存储数据,一个键(key)对应一个值(value),通过key来寻找value。如果抛开”键值对“不谈,那这就是一个完完全全的链表;那如果将key看成数组中的索引,value当成数组中的数组,那这就妥妥的是一个数组。与数组不同的是,数组里的索引是一开始就确定好了的,是固定的,而Hash里的key是利用value通过Hash函数计算出来的

​ 举个简单的例子,先假设有15,26,37,48四个数据,Hash函数采用除留余数法即H(value) = value MOD 10:

​ 将四个数据依次带入Hash函数中:

  • H(15) = 15 MOD 10 = 5 即Hash(5) = 15
  • H(26) = 26 MOD 10 = 6 即Hash(6) = 26
  • H(37) = 37 MOD 10 = 7 即Hash(7) = 37
  • H(48) = 48 MOD 10 = 8 即Hash(8) = 48

至此我们就完成了一个无碰撞的Hash数据表,这里采用的Hash函数比较简单,发生碰撞的概率非常大(这里没发生碰撞只是因为数据不多以及数据都是刻意挑选的),要想降低碰撞的可能可精心设计一个Hash函数,如可先将数据折叠或平方后再取模。当然常用的Hash函数还有很多,不必拘泥于这一种,常用的函数还有:

  • 直接寻址法
  • 数字分析法
  • 平方取中法
  • 折叠法
  • 随机数法
Hash碰撞解决:

​ 在简介中提到Hash函数是无法避免碰撞的,那就需要来处理这种情况的发生,通常采用链地址法开放地址法两种方法来处理碰撞。

  1. 链地址法

    ​ 运用一个链表数组来存储数据,如果发生碰撞,就将数据依次添加到对应的链表后面,这样就能够比较好的处理碰撞了。

    ​ 假设Hash长度为10,Hash函数采用上面“实现方法”中提到的函数,给定数据也还是采用上面的数据,再加上一个55(制造碰撞):
    在这里插入图片描述

  2. 开放地址法

    ​ 指利用大小为M的数据保存N个键值对(M>N)。线性探测法是一种比较常用的实现方式。此方法的核心思想是:一旦发生冲突,直接寻找下一个空闲的Hash表地址,只要这个表足够大,就一定能找到一个窝
    在这里插入图片描述
    ​ 数据55因为与15发生了碰撞,只得找下一个空闲的位置,而这个位置在“9”下面,因此才产生了这样一个Hash表。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值