Ответ
Двойное хеширование (Double Hashing) — это один из методов разрешения коллизий в хеш-таблицах, относящийся к классу техник открытой адресации.
В отличие от линейного или квадратичного пробирования, где шаг для поиска следующей ячейки фиксирован или предсказуем, в двойном хешировании этот шаг определяется второй, независимой хеш-функцией. Это помогает избежать первичной и вторичной кластеризации, распределяя элементы более равномерно по таблице.
Алгоритм:
- Вычисляется первичный хеш:
h1(key)
. - Если ячейка
h1(key)
занята, вычисляется вторичный хешh2(key)
, который определяет шаг смещения. - Последовательно проверяются ячейки:
(h1(key) + i * h2(key)) % tableSize
дляi = 1, 2, 3, ...
до тех пор, пока не будет найдена свободная ячейка.
Пример на Go (псевдокод):
// h1 и h2 - разные хеш-функции
// size - размер хеш-таблицы
func findSlotFor(key string, size int) int {
// Первичный хеш
h1 := hash1(key) % size
// Вторичный хеш для шага. Важно, чтобы h2 никогда не возвращал 0.
h2 := 1 + (hash2(key) % (size - 1))
for i := 0; i < size; i++ {
slot := (h1 + i*h2) % size
if isSlotEmpty(slot) {
return slot
}
}
// Таблица заполнена
return -1
}
Преимущества:
- Минимизирует кластеризацию: Значительно лучше, чем линейное пробирование, так как последовательности проб для разных ключей отличаются.
- Эффективное использование памяти: Не требует дополнительной памяти для хранения списков или деревьев, как в методе цепочек.
Недостатки:
- Вычислительная сложность: Требует вычисления двух хеш-функций вместо одной.
- Сложность реализации: Требуется подобрать хорошую вторую хеш-функцию, которая не возвращает ноль и значение которой является взаимно простым с размером таблицы.