码迷,mamicode.com
首页 > 编程语言 > 详细

MIT算法导论——第七讲.哈希表

时间:2015-05-19 00:52:06      阅读:316      评论:0      收藏:0      [点我收藏+]

标签:哈希表

从作用上来讲,构建哈希表的目的是把搜索的时间复杂度降低到O(1),考虑到一个长度为n的序列,如果依次去比较进行搜索的话,时间复杂度是θ(n),或者对其先进行排序然后再搜索会更快一些,但这两种方法都不是最快的方法。
哈希表也叫散列表,他通过一个哈希函数H,把要存储的内容取一个键值,经过H的运算,把键值映射到一个有m个槽的表中去,最简单的例子就是手机里存储别人的电话号码,键值就是名字,内容就是电话号码等个人信息。这样的表有一个最大的好处就是一旦要查找某个值,比如说“张三”的电话号码,我们把“张三”这个名字带入H函数,就能返回一个存储位置,比如说存在了号码本的第45个位置,我们就能立刻在这个位置搜索到“张三”的电话号码。

第一个话题:
计算机里面所有存储的内容都是数字,因此我们研究对数字构建哈希表就够了。先来考虑一下,一个好的哈希函数H需要哪些特点:
1.哈希函数的产生的键值要尽可能的均匀,不要出现聚集效应,也就是产生的各种h(k)要尽量的等概率的分布到哈希表的m个槽里去,当然,如果已经知道了输入的类型,我们可以设计出比较好的哈希函数,但是每一个哈希函数都有可能遇到一个特别针对他的输入,以至于所有计算的健值都指向同一个槽。
(一个哈希函数是否均匀的定义:x,y是两个不同的健值,哈希表的长度是m,P{h(x) = h(y)} =1/m ) 
2.哈希函数本身不能太复杂,以至于计算的时间过长。

例,一些简单的哈希函数:
1.直接哈希 h(k)=k,不会发生碰撞,但是占用空间大,没有意义
2.除法哈希 h(k)=k mod m ,m的取值很有讲究,不能去2和10的幂,这样很多内容都被mod掉了,而且不能取得太小等等等,可以考虑去一个合适的质数。由于计算机里经常用2和10的幂,不是很好用质数,而且还是除法,所以这种哈希效率也不是很高
3.乘法哈希,假设所有的key都是整数,m=2^r ,计算机字长是w,那么构建h(k)=(A*k mod 2^w) rsh (w-r) 其中rsh是右移的意思,A的大小是2^(w-1)<A<2^w 这个哈希函数的好处是,最后的取得h(k)实际上和每一位上的k值都相关,而A和2^w这两个数是互质的,所以想象一个轮盘,周长是2幂,A肯定不是周长的倍数,k是转了多少圈,那么最后的h(k)就会有可能落到轮盘的任意位置。

第二个话题:
就像之前提到的,无论设计一个怎样的哈希函数,碰撞都难以避免,那么如何来解决碰撞的问题呢?主要有以下两种方法:
1.链接法,每一次碰撞都添加一个链表,这样做会增加哈希表的大小,最坏的情况会导致所有的值都指向同一个槽,然后哈希表变成了一个链表,我们的查询也变成了链表的查询。
2.开放寻址法,在不增加哈希表容量的情况下,继续对该表进行“探测”,直到找到一个空位置把内容放进去。 wikipedia里面对此的解释是这样的(Open addressing, or closed hashing, is a method of collision resolution in hash tables. With this method a hash collision is resolved by probing

分析第一种方法——链表法:

在最坏的情况下,那就是所有的h(k)都指向了同一个槽,那么哈希表实际上就是一个链表,在链表中查询一个值的时间复杂度是θ(n),在最好的情况下,没有发生碰撞那么时间为θ(1)。定义α=n/m为哈希表的装载因子,一次成功的搜索平均用时θ(1+α/2)1表示计算H的时间,α/2表示在链表中所用的平均时间,所以如果n=O(m)那么α就是常数,在这个哈希表中搜索的时间就为θ(1),同时,考虑平均情况下的最坏情况的搜索,时间为θ(1+α),

分析第二种方法——“开放寻址”(封闭哈希)
这种方法主要通过“探寻”来在哈希表中寻找下一个空位置,把值存进去,查询的时候也采用同样的方法,一步一步查找到目标键值。
探寻的方法有:
1.线性探寻
2.非线性探寻
3.双重哈希探寻
4.伪随机序列探寻
这些方法都有一定的局限性,有可能造成顶级或者次级聚集
现在来分析开放寻址的效率,首先给出理论:对于一个开放寻址的哈希表,α=n/m<1,那么一次不成功搜索的预期探寻次数为1/(1-α).
由此可见,如果α=50% 那么预期探寻次数为2,如果α=90%,预期探寻次数将会显著升高到10,因此在这种策略下,α的大小至关重要(联想到同一天生日的问题,也是这个道理),在工程上某些采用此策略的哈希表会强制α小于75%,如果超过这个值会自动扩充哈希表。
预期探寻次数1/(1-α)是怎样算出来的,如下:
1.首先,查询一个值至少需要1次探寻
2.有n/m的可能性会发生碰撞,我们需要第二次探寻
3.有(n-1)/(m-1)的可能性第二次探寻也发生了碰撞
……
观察到(n-i)/(m-i)<α i=1,2,3……n
技术分享


MIT算法导论——第七讲.哈希表

标签:哈希表

原文地址:http://blog.csdn.net/persever/article/details/45773663

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!