散列(哈希)

1、为什么有哈希

       对于线性表、队列、树这些数据结构,它们的记录在结构中是随机的,而且和记录的关键字之间并不存在确定关系,查找某个元素时需要进行一系列与关键字的比较,即这种查找是建立在“比较”的基础上。所以查找的效率依赖于比较的次数,那么如何才能不经过比较直接找到记录所在位置呢?刚才说到上述数据结构的关键字与记录位置之间是不存在确定关系的,那么我们可以让这两者之间建立一种确定关系,也就是我们所说的对应关系f,使得每个关键字都与结构中一个唯一存储位置相对应。在查找时,通过给定值k以及对应关系f,便可以找到k值所对应的像f(k)。所以,在查找某个记录时,不需要比较便可以直接取得所查记录。那么这种对应关系 f 就是哈希函数,通过这个思想建立的表称为哈希表。

2、什么是哈希

       Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。

3、哈希函数

Hash函数特点:

  • 1. 输入域无穷,输出域有限。例如:有无穷多个(在工程中可以具体到多少个,例如1000)输入参数经过hash函数映射后得到有限的输出域{1,2,3,4}。
  • 2. 输入参数确定,经过hash函数映射出的返回值一样。(不是随机函数,不同的输入参数可能得到相同的返回值)。
  • 3. 输入域上的值经过函数值映射后会几乎均等的分布在输出域上。

(1)直接定址法

      取关键字或关键字的某个线性函数值为哈希地址。即H(key)=key 或 H(key)=a*key+b   (a,b为常数)。

(2)数字分析法

      若关键字是以r为基的数(如:以10为基的十进制数),并且哈希表中可能出现的关键字都是事先知道的,则可取关键字的若干数位组成哈希地址。

(3)平方取中法

      取关键字平方后的中间几位为哈希地址。(较常用的一种)

(4)折叠法

      将关键字分割成位数相同的几部分(最后一部分的位数可不同),然后取这几部分的叠加和(舍去进位)作为哈希地址。适用于关键字位数比较多,且关键字中每一位上数字分布大致均匀时。

(5)除留余数法

      取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址(p为素数)。

      H(key)=key  MOD  p,p<=m   (最简单,最常用)p的选取很重要

      一般情况,p可以选取为质数或者不包含小于20的质因数的合数(合数指自然数中除了能被1和本身整除外,还能被其他数(0除外)整除的数)。

 (6)随机数法 

      选择一个随机函数,把关键字的随机函数值作为它的哈希值。通常当关键字的长度不等时用这种方法。 

        构造哈希函数的方法很多,实际工作中要根据不同的情况选择合适的方法,总的原则是尽可能少的产生冲突。通常考虑的因素有关键字的长度和分布情况、哈希值的范围等。如:当关键字是整数类型时就可以用除留余数法;如果关键字是小数类型,选择随机数法会比较好

4、哈希冲突的解决

       选用哈希函数计算哈希值时,可能不同的 key 会得到相同的结果,一个地址怎么存放多个数据呢?这就是冲突。

常用的主要有两种方法解决冲突:

1.链接法(拉链法)

       拉链法解决冲突的做法是: 将所有关键字为同义词的结点链接在同一个单链表中。

2.开放定址法

       用开放定址法解决冲突的做法是:当冲突发生时,使用某种探测技术在散列表中形成一个探测序列。沿此序列逐个单元地查找,直到找到给定的关键字,或者碰到一个开放的地址(即该地址单元为空)为止(若要插入,在探查到开放的地址,则可将待插入的新结点存人该地址单元)。查找时探测到开放的地址则表明表中无待查的关键字,即查找失败。

       简单的说:当冲突发生时,使用某种探查(亦称探测)技术在散列表中寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到。

5、哈希表(散列表)

哈希表(hash table)是哈希函数最主要的应用。哈希表是实现关联数组(associative array)的一种数据结构,广泛应用于实现数据的快速查找。

        用哈希函数计算关键字的哈希值(hash value),通过哈希值这个索引就可以找到关键字的存储位置,即桶(bucket)。哈希表不同于二叉树、栈、序列的数据结构一般情况下,在哈希表上的插入、查找、删除等操作的时间复杂度是 O(1)。

        查找过程中,关键字的比较次数,取决于产生冲突的多少,产生的冲突少,查找效率就高,产生的冲突多,查找效率就低。因此,影响产生冲突多少的因素,也就是影响查找效率的因素。 
影响产生冲突多少有以下三个因素:

  1. 哈希函数是否均匀;
  2. 处理冲突的方法;
  3. 哈希表的加载因子。

        哈希表的加载因子和容量决定了在什么时候桶数(存储位置)不够,需要重新哈希。加载因子太大的话桶太多,遍历时效率变低;太小的话频繁 rehash,导致性能降低。所以加载因子的大小需要结合时间和空间效率考虑。在 HashMap 中的加载因子为 0.75,即四分之三。

分布式缓存

网络环境下的分布式缓存系统一般基于一致性哈希(Consistent hashing)。简单的说,一致性哈希将哈希值取值空间组织成一个虚拟的环,各个服务器与数据关键字K使用相同的哈希函数映射到这个环上,数据会存储在它顺时针“游走”遇到的第一个服务器。可以使每个服务器节点的负载相对均衡,很大程度上避免资源的浪费。

在动态分布式缓存系统中,哈希算法的设计是关键点。使用分布更合理的算法可以使得多个服务节点间的负载相对均衡,可以很大程度上避免资源的浪费以及部分服务器过载。 使用带虚拟节点的一致性哈希算法,可以有效地降低服务硬件环境变化带来的数据迁移代价和风险,从而使分布式缓存系统更加高效稳定。

 

 

参考:

http://www.nowamagic.net/librarys/veda/detail/1273

http://blog.csdn.net/cywosp/article/details/23397179/

http://www.cnblogs.com/qiaoshanzi/p/5295554.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值