Двойное хеширование - это метод компьютерного программирования, используемый вместе с открытой адресацией в хэш-таблицах для разрешения хэш-коллизий, используя вторичный хэш ключа в качестве смещения при возникновении коллизии. Двойное хеширование с открытой адресацией - это классическая структура данных в таблице .
Метод двойного хеширования использует одно хеш-значение в качестве индекса в таблице, а затем многократно продвигает интервал вперед до желаемого значения. обнаружено, достигнуто пустое место или произведен поиск по всей таблице; но этот интервал устанавливается второй независимой хэш-функцией . В отличие от альтернативных методов разрешения конфликтов линейного зондирования и квадратичного зондирования, интервал зависит от данных, поэтому значения, отображаемые в одно и то же место, имеют разные последовательности сегментов; это сводит к минимуму повторяющиеся коллизии и эффекты кластеризации.
Даны две случайные, однородные и независимые хэш-функции и , -е место в последовательности сегмента для значения в хеш-таблице buckets: Как правило, и выбираются из набора универсального хеша функции; выбран, чтобы иметь диапазон и , чтобы иметь диапазон . Двойное хеширование приближает случайное распределение; более точно, попарные независимые хеш-функции дают вероятность , что любая пара ключей будет следовать той же последовательности сегментов.
Вторичная хеш-функция должен иметь несколько характеристик:
In На практике, если для обеих функций используется хеширование деления, делители выбираются как простые числа.
Пусть будет количеством элементов, хранящихся в , тогда коэффициент нагрузки равен . То есть начните с случайного, равномерного и независимого выбора двух универсальных хэш-функций функций и для построения двойной хеш-таблицы . Все элементы помещаются в двойным хешированием с использованием и . Для ключа -й хэш-адрес вычисляется с помощью :
Пусть с фиксированным коэффициентом нагрузки .
<12097>Брэдфорд и Катехакис показал ожидаемое количество зондов для неудачного поиска в , все еще используя эти изначально выбранные хэш-функции, составляет независимо от распределения входных данных. Достаточно попарной независимости хэш-функций.Как и все другие формы открытых При адресации двойное хеширование становится линейным по мере приближения хеш-таблицы к максимальной емкости. Обычная эвристика заключается в ограничении загрузки таблицы до 75% емкости. В конце концов, потребуется повторное хеширование до большего размера, как и в случае со всеми другими схемами открытой адресации. с.
В диссертации Питера Диллинджера указывается, что двойное хеширование создает нежелательные эквивалентные хеш-функции, когда хеш-функции обрабатываются как набор, как в фильтрах Блума : Если и , затем и наборы хешей идентичны. Это увеличивает вероятность столкновения в два раза по сравнению с ожидаемым .
Кроме того, имеется значительное количество часто перекрывающихся хэш-наборов; если и , затем и сравнение дополнительных значений хеш-функции (расширение диапазона ) бесполезен.
Добавление квадратичного члена (a треугольное число ) или даже (тройное хеширование ) к хеш-функции несколько улучшает хеш-функцию, но не решает эту проблему; если:
, тогда
Добавление кубического члена или (a тетраэдрическое число ), действительно решает проблему, метод, известный как расширенное двойное хеширование . Это может быть эффективно вычислено с помощью прямого дифференцирования :
структурного ключа; // Непрозрачный extern unsigned int h1 (struct key const *), div class="ht" (struct key const *); // Вычислить k хеш-значений из двух базовых хеш-функций // h1 () и div class="ht" () с использованием расширенного двойного хеширования. При возврате // hashes [i] = h1 (x) + i * div class="ht" (x) + (i * i * i - i) / 6 // Использует преимущества автоматической упаковки (модульное сокращение) // беззнаковых типов в C. void hash (struct key const * x, unsigned int hashes, unsigned int n) {unsigned int a = h1 (x), b = div class="ht" (x), я; for (i = 0; i < n; i++) { hashes[i] = a; a += b; // Add quadratic difference to get cubic b += i; // Add linear difference to get quadratic // i++ adds constant difference to get linear } }