区域链准备篇:散列介绍(一)

散列

 散列表(hash table)的实现叫作散列(hashing)。
 散列是一种用于以常数平均时间执行插入、删除和查找的技术。

1. 散列基本想法
理想的散列表,数据结构只不过是一个包含一些项(item)的,具体固定大小的数组。
通常查找是对项的某个部分(数据域)进行,这部分叫关键字(key)。
散列表通常从0到TableSize-1变化,每个关键字被映射到0到TableSize-1这个范围中的某个数,并且被放到适当的单元中。这个映射过程叫散列函数(hash function)
通过一个散列函数,将关键字John散列到3….mary散列到7。 这里写图片描述
关键问题:选择一个函数,决定两个关键字散列到同一个值的时候(冲突collision),应该做什么以及如何确定散列表的大小。

2. 散列函数
如果关键字是整数,一般合理的函数就是之间返回Key mod TableSize。
如果关键字是字符串,散列函数需要仔细选择。如下一种↓

public static int hash(String key,int tableSize) {
        int hashVal=0;
        for(int i=0;i<key.length();i++)
            //hashVal+=key.charAt(i);
            hashVal=37*hashVal+key.charAt(i);
        hashVal=hashVal%tableSize;
        return hashVal<0?hashVal+tableSize:hashVal;
    }

例如”call”的哈希值,字符串c对应的unicode为99,a对应的unicode为97,L对应的unicode为108,所以字符串”call”的散列值为:

h = s[0] · 31L–1 + … + s[L – 3] · 312 + s[L – 2] · 311 + s[L – 1] · 310
3045982 = 99·313 + 97·312 + 108·311 + 108·310 = 108 + 31· (108 + 31 · (97 + 31 · (99)))

选择一个好的散列函数,剩下就要解决冲突问题,最简的两种:分离链接法和开放定址法。

3. 分离链接发
分离链接法(separate chaining),将散列到同一个值的所有元素保留到一个双向链接表中。

4. 开放定址法
探测散列表(probing hash table),不使用分离链接的散列表,其填装因子低于λ=0.5。

  1. 线性探测法

函数f是i的线性函数,典型情形是f(i)=i。寻找一个自由单元,把它放入这个空闲的开放地址中。费时间。

char[] s = str.ToCharArray();
int hash = 0;
for (int i = 0; i < s.Length; i++)
{
hash = s[i] + (31 * hash);
}
return hash;

  1. 平方探测法

消除线性探测中一次聚集的冲突解决方法。冲突函数是二次探测方法。典型情形是f(i)=i²。寻找i²的空闲地址填入。需要表的一半地址作备选,费空间。

  1. 双散列

双散列(double hashing)是将f(i)当作目标值,第一个散列函数,i作为一个寻找开放地址,第二个散列函数。典型的情形是f(i)=i·hash₂(x),hash₂(x)=x mod 9或者hash₂(x)=R-(x mod R)。理论可行,保证时间和空间。
具体代码参考博客:http://blog.csdn.net/u012124438/article/details/78230478

PS:负载因子
散列表中的键值对数与容量的比值叫做负载因子(load factor)。通常负载因子越小,我们进行查找所需时间就越短,而空间的使用就越大;若负载因子较大,则查找时间会变长,但是空间使用会减小。比如,Java标准库中的HashMap就是基于拉链法实现的散列表,它的默认负载因子为0.75。HashMap实现动态调整容量的方式是基于公式loadFactor = maxSize / capacity,其中maxSize为支持存储的最大键值对数,而loadFactor和capacity(容量)都会在初始化时由用户指定或是由系统赋予默认值。当HashMap中的键值对的数目达到了maxSize时,就会增大散列表中的容量。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值