我目前正处于接近学期结束的数据结构课程中,并且已经分配了一个项目,我们正在实施一个链接哈希表来存储和检索密钥。我们已经获得了相当大的自由度,我们将如何设计我们的哈希表实现,但是为了获得奖励积分,我们被告知尝试找到一个散列函数,将我们的密钥(唯一字符串)分布在整个接近均匀和随机的位置。桌子。
我选择使用ELF哈希,见http://www.eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx
我的问题如下:使用此哈希函数返回一个整数,但我无法看到如何使用它来帮助指定将我的密钥放入哈希表中的特定索引。我可以简单地做:index = ELFhash(String key)%tableSize,但这是否会破坏首先使用ELF哈希的目的?
此外,我选择了我的碰撞解决策略进行双重散列。有没有一种很好的方法来确定适当的二次散列函数来找到你的跳跃?我的哈希表不会是一个恒定的大小(将在我正在散列的数据集中添加和删除字符串集,并且我将在每次添加和删除迭代后重新运行它们以使其具有0.75的加载因子。 ),所以我很难做到像k%n这样的东西,其中n是一个与我的桌子大小相对较高的数字。
感谢您抽出宝贵时间阅读我的问题,并让我知道您的想法!
答案 0 :(得分:0)
你是否正确思考"包装偏见,"但是对于大多数实际目的来说,它不会成为问题。
如果哈希表的大小为N且哈希值在[0..M]范围内,则让k = floor(M/N)
。范围[0..k*N)
中的任何哈希值都是"好"其中之一是,使用mod N
作为映射,每个哈希桶都通过精确的k
哈希值进行映射。 [k*N..M)
中的哈希值为" bad"因为如果你使用它们,相应的M-K*n
最低哈希桶将从一个额外的哈希值映射。即使散列函数是完美的,这些桶也有更高的接收给定值的可能性。
但问题是,#34;还要多高?"这取决于M和N.如果哈希值是unsigned int
中的[0..2^32)
,并且 - 读过Knuth和其他人 - 你决定选择大约一千个桶的素数,比如1009,会发生什么?
floor(2^32 / 1009) = 4256657
"坏"值是
2^32 - 4256657 * 1009 = 383
因此,所有桶都是从4256657"好"映射的。价值,383得到一个额外的不想要的"坏"值为4256658.因此"偏见" for是1 / 4,256,657。
你不太可能找到一个哈希函数,其中桶之间的概率差异为1/4百万。
现在,如果你用一百万个桶而不是一千个重做计算,那么事情看起来会有所不同。在这种情况下,如果你有点OC,你可能想要切换到64位哈希。
另外一件事:Elf哈希不太可能给出绝对可怕的结果,并且它的速度非常快,但有更好的哈希函数。你可能想要尝试的一个相当受好评的是Murmur 32。 (Wiki的文章提到原始的alg有一些弱点可以用于DoS攻击,但是对于你的应用程序它会很好。)我确定你的教授不希望你复制代码,但是维基百科页面完成了它。自己实施Elf并尝试对抗Murmur以了解它们的比较将会很有趣。