散列表(Hash Table)

来源:互联网 发布:外貌协会的女生知乎 编辑:程序博客网 时间:2024/05/21 13:59

散列表也称作为哈希表,它是一个动态表,然而它支持字典的操作,因为它的存储一个值,需要相应的键。在查找一个值时,也需要一个键。最基本的操作就是:insert, search以及delete。散列表作为一个动态表,它的性能表现的异常好。甚至在合理的假设条件下,它的操作只需要O(1)的代价。
本章主要内容:
这里写图片描述

1. 直接地址法(Direct-address tables)

当我们的关键字全域U比较小时,直接寻址就显得十分有效,直接上图:
这里写图片描述
上图展示了,全域的大小就是表的大小,同时关键字只映射一个值。这个明显的一个缺点时,当我们的全域变得很大时,它就很会浪费空间。

2. 哈希函数(Hash function)

哈希函数的主要作用就是将我们的关键字映射成一个在哈希表中的位置。最基本的方法有除留余法,乘法散列,以及全域散列。在实际过程中我们用的更是复杂的哈希函数(如RS,JS),在这里我们只介绍全域散列。

全域散列

因为在实际当中,可能一个散列函数,会把许多关键子散列成同一个值,而实际当中最有效的方法就是,我们在一组不错的散列列函数,选择1个散列函数作为我们这1次的散列函数。如果又有一个关键字要散列的话,我们就从散列函数组中重新随机话选择1个散列函数进行散列。这样选中同一个的散列函数的可能性就会比较低,从而散列到同一个位置的可能性也十分低。因此它的平均性能也十分突出。

3. 碰撞冲突

碰撞冲突,主要是因为我们在散列的时候可能散列到同一个值,这样就会形成冲突。在这里我们主要有种方法解决冲突。链接法,再哈希以及开放定址法。开放地址法还有线性探查,二次探查以及双重散列。

链接法

直接上图更容易清楚:
这里写图片描述
从途中我们可以看出,当我们有散列值冲突的时候,我们就需要用一个双向链表将冲突的具有相同的散列值得关键字链在一起。这样就能够很好的解决冲突。
我们来分析其一般的性能:假设表长为m, 共有n个关键要散列。则我们可以算出表中每一个位置对应的元素长度:Θ(1+α)(其中的O(1)是用来计算哈希值的。
个人觉得其有一个不好的点:就是对于频繁删除和添加的操作则,要不断频繁的创造节点和删除节点,可能会消耗大量的时间,不过它的实现过程十分简单而且解决冲突的效果也是十分不错。

再哈希

当我们关键字在hash函数h1映射的时候发生了碰撞,然后选择另一个hash函数h2,h3,...hn直至没有冲突。这样做的缺点很明显,1是需要大量的hash函数,另外1个就是要不断的计算hash值。

开放定址法(open addressing)

线性探测(linear probing)

假设表长为m, 则散列函数如下:

h(k,i)=(h(k)+i)mod m,    i=0,1,2,...,m1

给定一个关键字k, 先用hash函数h()算出散列地址,探测这个位置是否冲突,如果冲突,则将地址+1直到没有冲突的位置。

二次探测(quadratic probing)

直接看散列函数:

h(k,i)=(h(k)+c1i+c2i2)mod m,    i=0,1,...,m1

和线性探测不同的时探测函数用的是二次函数。

双重散列(double hashing)

直接看散列函数:

h(k,i)=(h1(k)+ih2(k))mod m,    i=0,1,...,m1

3种开放定址法对比

通过图我们可以很容易看出他们之间的区别
1线性探测
这里写图片描述
2
这里写图片描述
3
这里写图片描述
从上面我们可以看出,双重散列更接近均匀散列。线性探测,可能导致查找的平均时间变长,而二次探测为了能够充分利用散列表,则c1,c2,m要受到限制。

均匀散列分析

定理3.1[1]

给定一个装载因子(loadfactor) α=n/m<1的开放寻址散列表,则对于一次不成功的探查次数至多为1/(1α)

定理3.2[2]

对于一个装载因子为α<1的开放寻址散列表,一次从成功查找中的探查期望数至多为

1αln11α

证明略,当nm=12时,探查期望小于1.387, 而当nm=0.9时, 探查期望小于2.559.[3]

4. 源码

本人在clion IDE中实现的, 下载请转此下载:http://download.csdn.net/detail/yzf0011/9772449

5. 感谢

本文是基于《算法导论》写的,最主要的是有本人大量的心得体会,感谢《算法导论》的那些作者Thomas H.Cormen、Charles E.Leiserson等 人。如果有错误的请留言,不甚感激。谢谢。

6. 参考

[1]《算法导论》Thomas H.Cormen、Charles E.Leiserson等 第三版第11章 “散列表” p155
[2]《算法导论》Thomas H.Cormen、Charles E.Leiserson等 第三版第11章 “散列表” p155
[3]《算法导论》Thomas H.Cormen、Charles E.Leiserson等 第三版第11章 “散列表” p155

转载,请注明

0 0