Хеширование кукушки — различия между версиями
(→Алгоритм) |
(→Алгоритм) |
||
| Строка 7: | Строка 7: | ||
Основная идея хеширования кукушки — использование двух хеш-функций вместо одной (далее <tex>h_1(x)</tex> и <tex>h_2(x)</tex>). Также есть вариант алгоритма, в котором используются две хеш-таблицы, и первая хеш-функция указывает на ячейку из первой таблицы, а вторая — из второй. Рассмотрим алгоритмы функций add(x), remove(x) и contains(x). | Основная идея хеширования кукушки — использование двух хеш-функций вместо одной (далее <tex>h_1(x)</tex> и <tex>h_2(x)</tex>). Также есть вариант алгоритма, в котором используются две хеш-таблицы, и первая хеш-функция указывает на ячейку из первой таблицы, а вторая — из второй. Рассмотрим алгоритмы функций add(x), remove(x) и contains(x). | ||
| − | Выберем 2 хэш-функции <tex>h_1(x)</tex> и <tex>h_2(x)</tex>. | + | Выберем 2 хэш-функции <tex>h_1(x)</tex> и <tex>h_2(x)</tex> (из [[Универсальное семейство хеш-функций | универсального семейства хэш-функций]]). |
'''Add''' — добавляет элемент с ключом <tex>x</tex> в хэш-таблицу | '''Add''' — добавляет элемент с ключом <tex>x</tex> в хэш-таблицу | ||
| − | # Если одна из ячеек с индексами <tex>h_1(x)</tex> или <tex>h_2(x)</tex> свободна, кладем в нее элемент. | + | # Если одна из ячеек с индексами <tex>h_1(x)</tex> или <tex>h_2(x)</tex> свободна, кладем в нее элемент. Проверяем, если хэш-таблица заполнена увеличиваем её размер. |
# Иначе произвольно выбираем одну из этих ячеек, запоминаем элемент, который там находится, помещаем туда новый. | # Иначе произвольно выбираем одну из этих ячеек, запоминаем элемент, который там находится, помещаем туда новый. | ||
| − | # Смотрим в ячейку, на которую указывает другая хеш-функция от элемента, который запомнили, если она свободна, помещаем его в нее. | + | # Смотрим в ячейку, на которую указывает другая хеш-функция от элемента, который запомнили, если она свободна, помещаем его в нее. Проверяем, если хэш-таблица заполнена увеличиваем её размер. |
# Иначе запоминаем элемент из этой ячейки, кладем туда старый. Проверяем, не зациклились ли мы. | # Иначе запоминаем элемент из этой ячейки, кладем туда старый. Проверяем, не зациклились ли мы. | ||
| − | # Если не зациклились, | + | # Если не зациклились, то продолжаем искать свободное место для очередных элементов. |
| − | # Иначе выбираем 2 новые хеш-функции | + | # Иначе выбираем 2 новые хеш-функции и перехешируем все добавленные элементы. |
| − | + | ||
| − | |||
Версия 20:34, 6 июня 2012
Хеширование кукушки — один из способов борьбы с коллизиями при создании хеш-таблицы.
Алгоритм
Основная идея хеширования кукушки — использование двух хеш-функций вместо одной (далее и ). Также есть вариант алгоритма, в котором используются две хеш-таблицы, и первая хеш-функция указывает на ячейку из первой таблицы, а вторая — из второй. Рассмотрим алгоритмы функций add(x), remove(x) и contains(x).
Выберем 2 хэш-функции и (из универсального семейства хэш-функций).
Add — добавляет элемент с ключом в хэш-таблицу
- Если одна из ячеек с индексами или свободна, кладем в нее элемент. Проверяем, если хэш-таблица заполнена увеличиваем её размер.
- Иначе произвольно выбираем одну из этих ячеек, запоминаем элемент, который там находится, помещаем туда новый.
- Смотрим в ячейку, на которую указывает другая хеш-функция от элемента, который запомнили, если она свободна, помещаем его в нее. Проверяем, если хэш-таблица заполнена увеличиваем её размер.
- Иначе запоминаем элемент из этой ячейки, кладем туда старый. Проверяем, не зациклились ли мы.
- Если не зациклились, то продолжаем искать свободное место для очередных элементов.
- Иначе выбираем 2 новые хеш-функции и перехешируем все добавленные элементы.
Remove — удаляет элемент с ключом из хэш-таблицы.
- Смотрим ячейки с индексами и .
- Если в одной из них есть искомый элемент, просто помечаем эту ячейку как свободную.
Contains — проверяет на наличие элемента в хэш-таблице
- Смотрим ячейки с индексами и .
- Если в одной из них есть искомый элемент, возвращаем true.
- Иначе возвращаем false.
Зацикливание
Зацикливание может возникнуть при добавлении элемента. Пусть мы добавляем элемент . И обе ячейки и заняты. Пусть, элемент положили в ячейку . Если в ходе перемещений элементов в таблице на очередном шаге мы опять хотим переместить элемент в ячейку , чтобы в ячейку поместить какой-то (это может произойти, если в ходе перемещений элемент был перемещен в ячейку ), то произошло зацикливание.
Например зацикливание возникнет если добавить в хэш-таблицу 3 элемента у которых = = и = = .
Время работы алгоритма
Удаление и проверка происходят за (что является основной особенностью данного типа хеширования), добавление в среднем происходит за . Первые два утверждения очевидны: требуется проверить всего лишь 2 ячейки таблицы.
| Утверждение: |
Добавление в среднем происходит за . |
| Один из способов доказательства данного утверждения использует теорию случайных графов. Это делается через неориентированный "кукушкин граф", где каждой ячейке хеш-таблицы соответствует ровно одна вершина, а каждому добавленному элементу — ребро с концами в вершинах, соответствующих ячейкам, в которые указывают хеш-функции элемента. При этом элемент будет добавлен без перехеширования тогда и только тогда, когда после добавления нового ребра граф будет оставаться псевдолесом, то есть каждая его компонента связности будет содержать не более одного цикла. |
Таким образом хеширование кукушки является одним из самых быстрых способов хеширования.