不发生冲突的Hash函数,你信喵?

  不发生冲突的Hash函数,你信喵?不管你信不信,反正我第一次看到时候是不信的喵~

  其实人家有个专门的名字叫作“完美哈希函数”——就是完全不会冲突的哈希函数。

  我想大家每次Hash-table的时候一定很讨厌冲突的存在,这时候你肯定是会想尽办法去避免过多冲突的出现。依我个人的经验,到最后很可能就是直接借用别人使用的hash函数了。

 

  要自己设计一个hash函数容易,但推导或证明其发生冲突的概率满足要求,这个就比较麻烦了喵~更何况这里是要求得到一个完全不冲突的函数。这简直是想都不敢想的事情了喵(我第一次看见完美hash函数时就是这种感觉)

 

  喵~说了这么多没营养的话喵~来点实用的喵~

  先来几个概念

哈希函数(Hash Function

  任意函数h(x)都可以说哈希函数,一般来说,一个良好的哈希函数可以尽量避免重复。x的集合是参数域,h(x)的集合是值域。

完美哈希函数(Perfect Hash Function

  完美哈希函数,就是完全不会冲突的哈希函数,这要求函数的值域不小于参数域

最小完美哈希函数(Minimal Perfect Hash Function

  最小完美哈希函数,就是指函数的值域和参数域的大小完全相等,一个也不多

保序最小完美哈希函数(Order Preserving Minimal Perfect Hash Function

  保序的意思就是指这个哈希之后顺序是不变的,同时还能满足其他两个条件。可以这样理解原来在前面的元素,哈希之后它也在前面。就和排序的稳定性是一个意思哦喵~

 

分析

  对于一个给定的数据集,我们可以构造出一个保序最小完美哈希函数(OPMPHF

  我们定义该函数为h(t):+n:在n的模域下进行加法)

  

  其中函数g(x)是需要我们去构造的,另两个函数h1(t)与h2(t)就是一般的哈希函数了。

  现在我们的目的就是去构造出一个函数g(x)使得h(t)成为一个保序最小完美哈希函数了喵~

  一种形像的理解就是:

    第0个元素t0经过h(t)后输出就为0

    第1个元素t1经过h(t)后输出就为1

    第x个元素tx经过h(t)后输出就为x

  那么具体怎喵构造这个函数呢?

  看上面那个式子,我们对于每个元素tx,我们已经通过两个哈希函数得到了它的两个哈希值,然后我们建一个图:
  对于有n个元素的序列,这个图里有n条边分别对应每个数据。边权值对应该元素在原序列中的序号,边的两个端点为该元素经过两个哈希函数之后的值。

即E(h1(tx), h2(tx)) = x

 

  正如大家所看到的一样,如果我们给每个点标记一个权值g(x),对于边E(a,b)

  我们要求的就是使得g(x)对于所有边,满足g(a) +n g(b) == E(a,b)

  对于一个一般图点标号问题来说,确实比较麻烦,但如果这个图有一个很好性质:无环。那么标号就变得异常的简单了喵~

  所以如果你不幸建个了一个有环图,那就重新选两个哈希函数再建一次图,直到建成无环图为止喵~这一句话看上去不怎喵靠谱吧喵~要建多少次才会出现无环图呢?我也觉得不怎喵靠谱的样子喵,可人家证明这样建图是可以接受的。

  然后剩下的问题就比较简单了喵~遍历图中所有顶点,当遍历到未标号顶点时,就以该点为根遍历该子树,并标号。(无环图就可以看作森林了喵~)

 

算法综述(生成一个完美哈希函数):

  1、随机选两个哈希函数

  2、生成一个图G=(V,E)

  3、判环与计算映射函数g(x)

  4、如果未得成功计算出g(x)(有环存在且破坏了g(x)函数),则重新执行该算法。

 

 

生成无环图的期望次数

 

参考:

  《深入搜索引擎》(Managing Gigabytes即MG)

  最小完美哈希函数简介

  “万里挑一”的最小完美哈希函数

 

posted on 2012-07-22 20:58  南柯一喵  阅读(4913)  评论(12编辑  收藏  举报