一个好的杂凑函数,可以把均匀的分布在杂凑表的每一个slot中,也就是尽量满足简单均匀杂凑的假设,而且分布的均匀性,不会受到元素的影响,也就是说,一个好的杂凑函数,我们希望它所产生的杂凑值,可以独立於输入的元素。
在杂凑函数中,除法杂凑法是很常见的杂凑函数,令为,杂凑表有个槽,我们通过取对的余数,将映射到的其中一个槽中,可以用以下的式子表示这个杂凑函数
使用这个杂凑函数时,我们需要避免一些情况的发生。
0010101011001, m=2^6,那麽我们会使用到的数字为
011001=h(k),而在二进位中,1和0的出现通常都具有一定的规律性,这会导致我们产生出的杂凑情况不够均匀
一般情况下,我们在取的时候,会选择一个不接近2的整数幕的质数,而这样取的情况下,往往会产生出比较好的结果。像是
除法杂凑法很常在程序中见到,因为他的程序码量不多,且效果不会太差,但相较於其他基於加法和乘法的杂凑函数,除法在电脑中需要花费更多的计算步骤,造成更多时间的消耗。
在实际处理资料时,我们常常无法事先得知的范围,或是具有的特性,像是全部都是偶数之类的,这时候,乘法杂凑表就是一个不错的方法可以使用。
假设,表示hash table的槽数,且在一部电脑中,每一个bytes含有 bits,则杂凑函数为
表示向右偏移(right shift)的意思,就是二进制的偏移, A是一个奇数,范围介於, 表示。
这个方法的关键在於的选取,在选取时我们必须避免选取一些特定的数值,像是选择时要尽量避免以2为底的数字,像是2,4,8,16等数字。
基本上这个方法是一个相当快速的方法,相乘後再取余数会比起直接除法要来的更快,且二进制的偏移运算本身就十分快速,尤其是在我们进行杂凑运算之前。我们就已经得知需要偏移的位元数的情况下,又来的更加的快速。
这个杂凑函数的关键就在於A的选取,假设A = 1011001(Bin) = 89(dec),2^w-1 = 64, 2^w = 128。
然後选取一个key来乘上A,k = 1101011,接着计算A * k
1011001 = A
* 1101011 = k
__________________
10010100110011
得到A和k的乘积後,接着对2^7取余数,也就是取出前7位数字
1001010__(0110011), 接着向右偏移(w-r)位,也就是(7-3)
0110011 >> (7-3) = 0000011,也就是取出最高位的前3位数字,而这个值就是h(k)了
而为什麽乘法杂凑法是一个很不错的演算法,我们引用下面图形进行说明,在说明之前,我们先进行一些假设
1011001 = A
* 1101011 = k
__________________
10010100110011
假设A是一个小於1的数,则我们可以在A的最高位天加上一个小数点,如下面所示
.1011001 = A
* 1101011 = k
___________________
1001010.0110011
而取余数的计算就是忽略掉整数部分,保留小数部分,以这个例子来说,A的小数部分以10进制来说大约是5.5左右。
而假设k = 1,2,3,4,5....
有了上面的假设,我们可以以一个环来表示一个规律
当k = 1时,A*k取小数部分大约为
当k = 2时,A*k取小数部分大概是
而乘法杂凑法就是运用这样的想法,让平均的分布在hash table中每一个槽里。而这也就是为什麽这是一个不错的杂凑方法,既可以保证计算的速度,又可以保证分布的平均性。
而先前提到的除法杂凑法,与乘法凑法对比在处理二进为资料时,由於取余数的部分还多出了hash table的槽位,和一个bytes的位元数等因子参与,因此增加了随机性,从而使乘法杂凑法成为了更好的策略可以使用。
而上面的范例是以7 bit进行示范,如果我们以64 bit表示,然後增加key的范围,那麽我们可以使最後产生出的杂凑值结果更加的随机,也就是对应到更多的槽位,使得碰撞的机率下降。
前面提到说,这个方法的好坏取决於我们如何选取,对於某一些值,这个方法的效果特别的好,根据Knuth认为,如果趋近於黄金比例常数的共轭根
产生出的结果会较为理想。
参考资料:Introduction to algorithms 3rd
<<: Day 23 [Python ML、资料视觉化] 直方图、密度图
大家好我是乌木白,今天来向大家介绍GitHub,我自己很喜欢的一个可以做很多功能的网站!! 什麽是...
分享完关於图片的排版设计,今天我们就来进行排版的实作啦! 之前有介绍过的<float>&...
一个人应该:活泼而守纪律,天真而不幼稚,勇敢而不鲁莽,倔强而有原则,热情而不冲动,乐观而不盲目。 《...
前言 JavaScript 内的物件都有内建的两个属性,可以实现对物件的存取,称为: getter ...
今晚我想来点... 麻而不辣的 linker script [叮咚] 您的外送餐点到瞜, 已经依照您...