Как работает функция хеширования MAD (умножение, добавление, деление)? - PullRequest
1 голос
/ 19 мая 2019

Мне в качестве университетского проекта была назначена задача создания структур данных (таких как minheap, hashtable и т. Д.) С нуля. Однако функции Hashtable или, точнее, Hash maps - доставили мне немало хлопот. Я сталкивался с функцией MAD ​​(Умножить, Добавить, Разделить), которая в основном: h (x) = [(a * x + b)% p]% N, где a, b: случайные целые числа, p: большое простое число и N: количество элементов в хеш-таблице.

Мой вопрос заключается в том, как (и почему) именно эта функция равномерно распределяет значения в хеш-таблице.

1 Ответ

1 голос
/ 22 мая 2019

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

Давайте сначала рассмотрим a*x + b в изоляции.Если вы представите, что a разбит на сумму степеней двух, a*x - это тогда сумма x битов, сдвинутых влево на совокупность степеней двух, так что каждый бит в x влияет на другие позиции битов.которые установлены в a, и некоторые дополнительные биты, когда суммирование производит переносы в определенных битах.Добавление b микширует в другой набор случайных битов: очень похоже на XORing, но с некоторой дополнительной сложностью от переносов.Если, скажем, x имеет значение между 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""столбец мы суммируем h и P, который может переноситься в столбец" 2s "с g, h и O, и далее он идет.

Если a скажем, 37, то есть 32 + 4 + 1, затем мы добавляем x, x << 2 и x << 5: каждый бит в x, таким образом, влияет на большее количество бит в значении хэша (это хорошодействительно с хэш-функцией криптографической стойкости, изменение любых битов в ключе - будь то один бит, половина или все они - должно в значительной степени случайным образом перевернуть примерно половину бит в значении хэша).

Возвращениев полной формуле давайте представим, что мы пропустили % p и имели только % N, но текущий размер таблицы равен степени двух: % N тогда эквивалентно операции побитового И для некоторого числа менее значимыхбиты.Иными словами, он отбрасывает большую часть случайности, которую мы создали в более значимых битах нашего a * x + b вычисления.Таким образом, чтобы сделать хеш-функцию безопасной для использования с любым количеством сегментов, мы можем сначала ввести % p, что означает, что если в значении хэша есть шаблоны, связанные с степенями двух позиций на этапе суммирования, ониэффективно разбросаны по случайным позициям в диапазоне 0..p.

Рассмотрим, скажем, хэш от 0 до 255 - если бы N равнялось 200, мы бы в два раза с большей вероятностью хешировали ведро в 0..55 диапазонЧтобы сделать этот эффект менее значимым, мы хотим, чтобы значение хеша имело намного больше битов, чем значение MOD, и этот принцип применяется многоуровневым способом к значениям, которые мы должны выбрать для p и N:

  • a * x + b значения должны иметь тенденцию быть значительно большими, чем p, и распространяться по диапазону, намного большему, чем p, поэтому % p разделяет их больше по сегментам, но

  • p должно быть намного больше, чем N, поэтому у нас нет низкоиндексированных сегментов со значительно более высокой вероятностью столкновений (что особенно плохо, если вы используете линейное зондирование для разрешенияколлизии).

Например, если мы хотим поддерживать значения от N до 2 24 , и мы выполняем эти вычисления с 32-битным беззнаковымцелые числа, так что a и b имеют случайные значения в этом диапазоне, мы могли бы разделить разницу, выбрав простое число около 2 28 .

...