Универсальное хеширование позволяет генерировать случайную хеш-функцию, обеспечивающую равномерное распределение значений хешей
Для того, чтобы последнее было верно, количество функций , для которых , не должно превышать
Для универсального хеширования при использовании метода цепочек время выполнения операций любых операций равно
Хеш-функция принимает 1 аргумент. Поскольку для реализации неудобно хранить полный набор всех хеш-функций, нужны правила, по которым хеш-функция будет параметризоваться, либо при инстанцировании, либо другим способом.
Универсальная хеш-функция параметризуется двумя случайными параметрами , а также простым числом таким, что максимальный ключ :
Пример на псевдо-python
class UniversalHash:
def __init__(self, max_key, m): # конструктор
self._m = m
self._p = self.generate_prime_greater_than(max_key)
self._a = random.randint(0, self.p)
self._b = random.randint(1, self.p)
def hash(self, key): # self - указатель на сам объект
return (((self._a * key + self._b)
% self._p)
% self._m)
def generate_prime_greater_than(self, max_key):
...
return p
При инстанцировании hash_fn = UniversalHash(max_key, m) вычисляется параметр и случайным образом выбираются два параметра . При вызове метода hash_fn.hash(key) будут создаваться значения хешей, соответсующие требованию вероятности коллизий не более .
Фактически, класс UniversalHash описывает построение универсального класса (или множества) хеш-функций. Осталось только разобраться в генерации параметров и наложенных на них ограничениях, а так же разобраться в корректности работы алгоритма.
( это множество целых чисел)
Например, если максимальный ключ - , , мы выбираем случайным образом и из множеств .
В этом случае хеш-функция равна, например,
Если размер таблицы равен , мы получим такие значения:
...
Для некоторых значений количество коллизий для конкретной хеш-функции может быть больше, для некоторых - меньше, но в среднем будет , и сейчас мы докажем это.
- множество универсальных хеш-функций для всех ключей меньше и таблицы размера
(на практике может быть равно, например, простому числу и т.д., а - любому размеру таблицы, так как данный метод не накладывает на размер таблиц дополнительных ограничений)
В этом множестве существует возможных хеш-функций (т.к. есть вариантов выбора и вариантов выбора ).
Для двух ключей , и определенной , "внутреннее" отображение будет таким:
фактически, любой ключ из изменяется и переходит в то же множество
Вычтем из :
Покажем, что для любой пары также верно . Это верно, поскольку - простое число, следовательно, и отличны от нуля по модулю , и их произведение также отлично от нуля по модулю .
мы можем вычитать , предполагая без потери общности, что всегда, поскольку можем выбирать имена переменных произвольно.
Итак, коллизии для произвольной (поскольку выбирались случайно и проивзольно) функции из множества не могут случиться.
Далее, можно показать, что "внутреннее" отображение биективно. Тогда из биективности отображения и пары случайного равновероятного выбора из следует, что случайно и равномерно распределенные переменные.
Каждая из возможных пар может быть найдена по значениям ключей и паре (и ) однозначно:
можно выразить без использования :
- число, обратное по модулю; то есть
из этого можно сделать вывод, что каждая пара дает различные пары .
Количество пар и одинаково и равно ; отсюда и появляется биективность отображения из множества пар в множество пар .
Итак, пара с равной вероятностью может быть любой из пар с различающимися по модулю значениями, что следует из биективности отображения и характера выбора чисел и .
Осталось только показать, что вероятность коллизии значений после взятия модуля по не превышает .
Эта вероятность будет равна вероятности совпадения значений и по модулю : .
Если зафиксировать , останется возможных значений . Из них по , совпадающих по модулю с , будет не больше, чем .
так происходит потому, что поскольку по модулю может совпадать не более, чем каждое -тое число, и надо посчитать количество возможных интеровалов размера , округлить значение вверх и вычесть единицу (1 интеравал будет неполным)
Поделив это значение на количество возможных , получим вероятность коллизии:
Итак, было показано, что для любой пары и для любой случайно выбранной функции вероятность коллизии равна , то есть множество функций является универсальным.
Этот алгоритм будет применен далее как основа алгоритма создания идеальной хеш-функции для заранее известного набора данных
Краткий список основных формул (без доказательств):
</font>