算法打基础——HashⅡ: 全域哈希与完美哈希
这一节涉及数学超级多,各种数论知识,各种不明觉厉! 看了几遍,才勉强看懂一些,所以这
篇稍微简单的介绍着两种hash table, 免得瞎说说错了。
这一讲的主要知识点是:1. 全域哈希及构造 2. 完美哈希
1. 全域哈希及构造
介绍全域哈希之前,要先讨论一下普通哈希的一个缺点。 举个charles举得那个例子:如果你
和一个竞争对手同时为一家公司做compiler的symbol table, 公司要求你们代码共享
(o(╯□╰)o),你们做好后公司评判的标准就是 你俩互相提供一些测试样例,谁的效率高就买谁的。
然后,普通哈希的缺点就出来了:对任意的hash函数h,总存在一组keys,使得
, 对某个槽i。即我总可以找到一组键值,让他们都映射到同一个槽里面,这样效率
就跟离链表差不多了
解决的思想就是:独立于键值,随机的选择hash 函数。这就跟快排中为避免最差情况时随机化
版本差不多。但是选取hash function的全局域是不能乱定的,否则也打不到理想的性能。
下面就给出全域哈希的定义:
设U是key的全局域, 设\(\mathcal{H}\) 是哈希函数的有限集合,每一个都是将U映射到
{0,1,..,m-1},即table的槽内。 如果对所有不等的\(x,y\in U\),有
换句话说,就是对于任意的不相等key的x和y, 从哈希函数集中选择一个哈希函数,这两个key
发生冲突的概率是1/m
更形象的,当我随机选一个哈希函数时,就像在上图区域乱扔一个飞镖,落在下面红色区域中
就会发生冲突,这个概率是1/m
下面给一个定理,说明为什么全域函数就是好的:
设h是从哈希函数全域集\(\mathcal{H}\)中随机选出的函数h. h被用作把任意n个键映射到表T的m个
槽中,对给定键值x,我们有:
定理:E[#collision with x]<n/m
Proof: 设\(C_x\)是表示与key x冲突的键值数量的随机变量,设\(c_{xy}\)是指示变量,即
则,\(E[c_{xy}]=1/m\) 且\(C_x=\sum_{y\in T-\{x\}}c_{xy}\),则
证毕!
这个定理想要说明的是,这种全域哈希的随机化选择可以达到哈希表理想的效果。注意这里
n/m是之前定义过的load factor
现在给出一种构造全域哈希的方法:
首先选择一个足够大的质数p,使得所有的键值都在0-p-1之间。且设\(Z_p\)表示{0,1,...,p-1},设
\(Z_p^*\)表示{1,2,..,p-1}. 因为槽m的数量少于key的数量,所有m<p.
然后我们就可以设计哈希函数了,设任意的\(a\in Z_P^*,b\in Z_p\),然后
\(h_a,b(k)=((ak+b)mod p)mod m\)
所有这样的哈希函数族为:
\(\mathcal{H}_{p.m}=\{h_{a,b}:a\in Z_p^*, b\in Z_p\}\)
例如:选定p=17,m=6,\(h_{3,4}(8)=5\). 每个哈希函数都是将\(Z_p\)映射到\(Z_m\). 我们还
可以看到这个哈希函数族共有p(p-1)个哈希函数
针对这种构造方法构造出的是全域哈希函数的证明就略过了,涉及数学知识确实比较多,讲不好。
2. 完美哈希
当键值是static(即固定不变)的时候,我们可以涉及方案使得最差情况下的查询性能也很出色,这就是
完美哈希。实际上,很多地方都会用到静态关键字集合。比如一种语言的保留字集合,一张CD-ROM
里的文件名集合。 而完美哈希可以在最坏情况下以O(1)复杂度查找,性能非常出色的。
完美哈希的思想就是采用两级的框架,每一级上都用全域哈希
完美哈希的结构如上图。具体来说,第一级和带链表的哈希非常的相似,只是第一级发生冲突后后面接
的不是链表,而是一个新的哈希表。后面那个哈希结构,我们可以看到前端存储了一些哈希表的基本
性质:m 哈希表槽数;a,b 全域哈希函数要确定的两个值(一般是随机选然后确定下来的),后面跟着
哈希表。
为了保证不冲突,每个二级哈希表的数量是第一级映射到这个槽中元素个数的平方,这样可以保证整个
哈希表非常的稀疏。下面给出一个定理,能更清楚的看到设置m=n^2的作用
定理:设\(\mathcal{H}\)是一类全域哈希函数,哈希表的槽数m=n^2. 那么,如果我们用一个随机
函数\(h\in\mathcal{H}\)把n个keys映射到表中。冲突次数的期望最多是1/2.
Proof:根据全域哈希的定义,对任意选出的哈希函数h,表中2个给定keys冲突的概率是1/m,即1/n^2
且总共有\(C_n^2\)可能的键值对,那么冲突次数的期望就是
\(C_n^2\cdot 1/n^2=n(n-1)/2\cdot 1\n^2 < 1/2\) 证毕!
为了冲突的理解从期望转换到概率,引入下面这个推论
推论: 完美哈希没有冲突的概率至少是1/2
Proof: 这里主要要用到一个不等式Markov's inequality-对任意非负随机变量X,我们有
Pr{X≥t}≤E[x]/t
利用这个不等式,让t=1,即可得到冲突次数大于1的概率最多为1/2
因为第二层每个表槽的个数是这个表中元素n^2,可能会感觉到这样存储空间会很大,实际上,可以证
明\(E[\sum_{i=0}^{m-1}\Theta(n_i^2)]=\Theta(n)\), 因为证起来蛮复杂,所以我也略过了%>_<%
最后,向各位大牛们提个问题,看到了请一定要教我! 怎么在博客园里面更美观的插入大量数学公式
(最好是用latex语法),支持分多行对齐等结构,现在不会,证明公式都没办法写,写出来也难看。跪谢!
算法打基础——HashⅡ: 全域哈希与完美哈希的更多相关文章
- 查找算法(7)--Hash search--哈希查找
1.哈希查找 (1)什么是哈希表(Hash) 我们使用一个下标范围比较大的数组来存储元素.可以设计一个函数(哈希函数, 也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标)相对应,于是用 ...
- 算法初级面试题05——哈希函数/表、生成多个哈希函数、哈希扩容、利用哈希分流找出大文件的重复内容、设计RandomPool结构、布隆过滤器、一致性哈希、并查集、岛问题
今天主要讨论:哈希函数.哈希表.布隆过滤器.一致性哈希.并查集的介绍和应用. 题目一 认识哈希函数和哈希表 1.输入无限大 2.输出有限的S集合 3.输入什么就输出什么 4.会发生哈希碰撞 5.会均匀 ...
- 《算法 - 一致性 (hash) 算法》
图片摘自: 每天进步一点点——五分钟理解一致性哈希算法(consistent hashing) 一:背景 - 一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的. ...
- 算法打基础——HashTable
这一节主要讲很多方面非常重要的hash table等问题. 由于平时很少用到这些,基本都忘了... 怎样快速的在内存中插入.删除.和搜索呢? 这就需要哈希表了 这一节主要知识点是:1 简单的映射表和处 ...
- KMP替代算法——字符串Hash
很久以前写的... 今天来谈谈一种用来替代KMP算法的奇葩算法--字符串Hash 例题:给你两个字符串p和s,求出p在s中出现的次数.(字符串长度小于等于1000000) 字符串的Hash 根据字面意 ...
- 算法<初级> - 第二章 队列、栈、哈希表相关问题
算法 - 第二章 数据结构 题目一 用数组实现大小固定的队列和栈(一面题) 数组实现大小固定栈 /*** * size是对头索引(initSize是固定大小) 也是当前栈大小 * size=下个进队i ...
- 哈希,哈希表,哈希Map
数组: 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1):数组的特点是:寻址容易,插入和删除困难: 链表: 链表存储区间离散,占用内存比较宽松,故空间复杂 ...
- RK哈希(Rabin_Karp 哈希)
Rabin_Karp 哈希通过比较hash值是否相等来比较每个字符串是否相等有概率出错(很小)字符串x1,x2,x3……xk基底e;模数mo;hash=(xk*e^0+xk-1*e^1+......+ ...
- Java集合(八)哈希表及哈希函数的实现方式
Java集合(八)哈希表及哈希函数的实现方式 一.哈希表 非哈希表的特点:关键字在表中的位置和它之间不存在一个确定的关系,查找的过程为给定值一次和各个关键字进行比较,查找的效率取决于和给定值进行比较的 ...
随机推荐
- bigdata_ambari修改hiveserver_metastore链接库(从0.14 升级到1.2.1 )
第一步:[db升级 ,先看第二步] cd到 hive的 metastore upgrade目录 cd /usr/hdp/2.5.0.0-1245/hive/scripts/metastore/upg ...
- VS解决方案创建
示例VS解决方案的创建(一) 进行项目开发的第一步,是创建出适合自己团队习惯的VS解决方案,虽然我已经提供了项目示例,但毕竟是我创建的,你直接使用可能并不合适,另外你如果尝试模仿重新创建该示例,中 ...
- linux后台server开发环境的部署配置和验证(nginx+apache+php-fpm+FASTCGI(C/C++))
linux后台server开发环境部署配置 引言 背景 随着互联网业务的不断增多.开发环境变得越来越复杂,为了便于统一server端的开发部署环境,特制定本配置文档. 使用软件 CentOS 6.3( ...
- jQuery遍历table中间tr td并获得td价值
jQuery遍历table中间tr td并获得td中间值 $(function(){ $("#tableId tr").find("td").each(func ...
- POJ1258 基础最小生成树
本文出自:http://blog.csdn.net/svitter 题意:给出一个数字n代表邻接矩阵的大小,随后给出邻接矩阵的值.输出最小生成树的权值. 题解: prime算法的基本解法: 1.选择一 ...
- C++外观设计模式模式(三)
3.外观模式总结 引入了外观类.解除了客户类与子系统的耦合性.客户类不须要直接操作子系统,而是由外观类负责处理,对client而言是透明的,客户类仅仅须要操作外观类就能够了,符合"迪迷特法则 ...
- ASP.NET Web API和ASP.NET Web MVC中使用Ninject
ASP.NET Web API和ASP.NET Web MVC中使用Ninject 先附上源码下载地址 一.准备工作 1.新建一个名为MvcDemo的空解决方案 2.新建一个名为MvcDemo.Web ...
- Performing User-Managed Database-18.4、Restoring Datafiles and Archived Redo Logs
18.4.Restoring Datafiles and Archived Redo Logs 假定介质故障损坏的一个或多个数据文件,数据文件必须恢复损坏的文件之前恢复. 该位置是不是想恢复原来姿势. ...
- UIAutomator源码分析之启动和运行
通过上一篇<Android4.3引入的UiAutomation新框架官方简介>我们可以看到UiAutomator其实就是使用了UiAutomation这个新框架,通过调用Accessibi ...
- MPEG-DASH on IIS Practice in Action
1. 准备 IIS Media Service已经安装准备好(如上),注意需要在2008上安装,2003安装不了,或者就算能安装也很麻烦 一个或多个码率的媒体文件如MP4已经准备好 DASH MPD ...