Расширяемое хеширование
При частом добавлении новых значений в хеш-таблицу может возникнуть ситуация, когда хеш-таблица становится полностью заполненной и требуется перехешировать ее. Но при больших размерах хеш-таблицы это требует большого количества времени. Чтобы решить эту проблему, а также чтобы не выделять много дополнительной памяти можно использовать расширяемое хеширование.
Структура и алгоритм
Метод расширяемого хеширования (англ. extendible hashing) заключается в том, что хеш-таблица представлена как каталог (англ. directory), а каждая ячейка будет указывать на емкость (англ. bucket) которая имеет определенную вместимость (англ. capacity). Сама хеш-таблица будет иметь глобальную глубину (англ. global depth), а каждая из емкостей имеет локальную глубину (англ. local depth). Глобальная глубина показывает сколько последних бит будут использоваться для того чтобы определить в какую емкость следует заносить значения. А из разницы локальной глубины и глобальной глубины можно понять сколько ячеек каталога ссылаются на емкость. Это можно показать формулой
где — глобальная глубина, а — локальная глубина. Если емкость куда следует положить значение переполнена, то смотрим на локальную глубину емкости. Если она меньше чем глобальная глубина то значит на емкость есть несколько указателей и нам достаточно перехешировать ее, разделив при этом на две и занести значения в новые две емкости увеличив у этих емкостей локальную глубину на . Если же локальная глубина была равна глобальной то мы увеличиваем глобальную глубину на , удваивая при этом количество ячеек, количество указателей на емкости, а также увеличиваем количество последних бит по которым мы распределяем значения. Далее локальная глубина переполненной емкости становится меньше и мы знаем что дальше делать.Пример
Рассмотрим алгоритм на примере.
Пусть у нас есть некий каталог со своими указателями и мы хотим добавить значения
(см. рис1) где — глобальная глубина, — локальные глубины емкостей, а вместимость емкостей равна . Рассмотрим значение . В двоичном коде оно равно . Окончание соответствует второй ячейке значит смотрим на вторую емкость. В ней есть свободное место и мы просто помещаем в нее (см. рис2). Далее идет значение . В двоичном виде оно представляется как . Это значение оканчивается на и должно пойти в первую емкость, но первая емкость полностью заполнена. Следовательно мы смотрим на . а значит мы должны удвоить количество ячеек каталога, увеличить глобальную глубину, затем увеличить количество последних бит по которым мы раскидываем значения на и перехешировать первую емкость, разделив ее на две, увеличив локальную глубину и разместив значения по новым емкостям (см. рис3). Теперь рассмотрим последнее число . Его двоичное представление — . Последние бита соответствуют третьей емкости, но она также полностью заполнена как и во втором случае, но ее локальная глубина меньше чем глобальная а следовательно нам надо только перехешировать емкость, разделив ее на две, увеличив локальную глубину и разместив значения по новым емкостям (см. рис4).Использование
Чаще всего расширяемое хеширование используется в базах данных т.к. БД могут быть крайне большими и перехеширование всей БД займет продолжительное время при этом лишая пользователей доступа к БД. А при использовании расширяемого хеширования перехешировать придется только малые группы, что не сильно замедлит работу БД.
См. также
Источники информации
- Бакнелл Джулиан — Фундаментальные алгоритмы и структуры данных в Delphi — стр. 50.
- Дейт К. Дж. — Введение в системы баз данных, 8-е издание.: Пер. с англ. — М.: Издательский дом «Вильямс», 2005. — стр. 1236.