【问题标题】:How does the MAD (Multiply, Add, Divide) Hashing function work?MAD(乘、加、除)哈希函数如何工作?
【发布时间】:2019-10-06 03:55:33
【问题描述】:

作为一个大学项目,我被分配了从头开始创建数据结构(例如 minheap、hashtable 等)的任务。然而 Hashtable 或更具体地说是 Hash maps - 函数给我带来了一些麻烦。我遇到了 MAD(乘、加、除)函数,它基本上是:h(x) = [(a*x + b) % p] % N,其中 a,b:随机整数,p:大素数和 N :哈希表中的元素数。

我的问题是这个函数如何(以及为什么)准确地均匀分布哈希表中的值。

【问题讨论】:

  • 谁说的?顺便说一句,这似乎是数学问题而不是编程问题。
  • 嗯,我是堆栈溢出的新手,这里似乎是提出这个问题的更好的地方,因为它与数据结构有关,但是我知道你来自哪里,因为它涉及到数学方面。无论如何,我也认为它没有那么有效,但是我们的教授建议我们使用它。
  • 我遇到了 MAD 功能你有这个链接,你可以edit 进入你的问题吗?
  • 我不明白我应该在问题中编辑什么?
  • 你是从哪里看到这个描述的?如果我们可以阅读相同的资料,我们可以更好地解释哪些内容有效(或无效)。

标签: c++ hashmap hashtable


【解决方案1】:

h(x) = [(a*x + b) % p] % N

让我们先单独看看a*x + b。如果您将a 分解为 2 的幂的总和,则a*xx 的总和,左移了少量的 2 的幂,这样x 中的每个位都会影响其他位位置在a 中设置的值,以及在求和产生特定位进位时的一些其他位。添加b 会混合另一组随机位:很像异或运算,但进位会带来一些额外的复杂性。如果说x has 是一个介于 0 和 255 之间的值,位为 abcdefgh(每个为 0 或 1),那么到目前为止我们已经得到:

         (a&1 ? abcdefgh : 0) +
        (a&2 ? abcdefgh0 : 0) +
       (a&4 ? abcdefgh00 : 0) +
      (a&8 ? abcdefgh000 : 0) +
                     ...      +  // continues for a&16, a&32 etc.
        ABCDEFGHIJKLMNOP         // however many random bits in "b"

因此,在“1s”列中,我们将 hP 相加,这可能会与 ghO 一起进入“2s”列,然后继续。

如果a 是 37,即 32+4+1,那么我们将添加 x 本身、x << 2x << 5x 中的每个位因此会影响更多位散列值(这很好,确实使用加密强度散列函数,更改密钥中的任何位 - 无论是单个位,一半还是全部 - 应该几乎随机翻转散列值中大约一半的位)。

回到完整的公式,假设我们跳过了% p,只有% N,但当前表大小是2的幂:% N 就相当于对某个数字进行按位与运算不太重要的位。换句话说,它丢弃了我们在a * x + b 计算的更重要位中建立的大量随机性。因此,为了使哈希函数可以安全地用于任意数量的桶,我们可以首先引入% p,这意味着如果哈希值中存在与求和步骤中的二次幂位置相关的模式,它们是有效地分散在 0..p 范围内的随机位置。

假设一个介于 0 和 255 之间的哈希值 - 如果 N 为 200,我们将哈希值放入 0..55 范围内的存储桶的可能性会增加一倍。为了使这种影响不那么显着,我们希望哈希值比 MOD 值有更多的位,并且这个原则以分层方式适用于我们应该为 pN 选择的值:

  • a * x + b 值应该明显大于p,并且分布在比p 大得多的范围内,因此% p 将它们更多地分隔在存储桶中,但是

  • p 应该比N 大得多,因此我们没有具有显着更高碰撞概率的低索引存储桶(如果您使用线性探测来解决冲突,这尤其糟糕)。

例如,如果我们想支持 N 的值最大为 224,并且我们使用 32 位无符号整数进行这些计算,因此 ab 具有随机在该范围内的值,我们可能会分裂选择大约 228 左右的质数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-07
    • 2017-03-05
    • 2010-10-18
    • 2012-01-03
    • 2021-01-23
    • 2012-08-05
    相关资源
    最近更新 更多