
Метод поиска хеширование
Теоретическая часть
Описание метода
Для ускорения доступа к данным в таблицах можно использовать предварительное упорядочивание таблицы в соответствии со значениями ключей. При этом могут быть использованы методы поиска в упорядоченных структурах данных, например, метод половинного деления, что существенно сокращает время поиска данных по значению ключа. Однако при добавлении новой записи требуется переупорядочить таблицу. Потери времени на повторное упорядочивание таблицы могут значительно превышать выигрыш от сокращения времени поиска. Поэтому для сокращения времени доступа к данным в таблицах используется так называемое случайное упорядочивание или хеширование. При этом данные организуются в виде таблицы при помощи хеш-функции h, используемой для ⌠вычисления■ адреса по значению ключа.
Характеристики метода
Вырожденный пример абсолютно совершенной хеш-функции приведен на рисунке, где ключами являются коды заглавных букв латинского алфавита (в кодировке ASCII), а хэш-функция отрезает от кода буквы младшие пять бит.
В более сложных случаях для построения совершенной хеш-функции используются специальные программы (основанные на эмпирических алгоритмах), которые по заданному набору ключей генерируют функции отображения ключей в индексы массивов хранимых записей. Вообще говоря, выработанная совершенная хеш-функция не гарантирует, что все элементы массива будут заполнены записями, соответствующими значениям ключей. Более того, при добавлении хотя бы одного нового ключа к ранее заданному набору потребуется генерация новой хеш-функции и соответствующая ей перестановка элементов массива записей.
Визуализация метода
Заключение
Прием совершенного хеширования дает превосходные результаты при задании известного заранее не очень большого набора ключей, но не помогает в случае необходимости динамического включения или исключения записей.
Реализация метода на TurboPascal
function hash (key : string[4]): integer;
var
f: longint;
begin
f:=ord (key[1]) - ord (key[2]) + ord (key[3]) -ord (key[4]);
{вычисление функции по значению ключа}
f:=f+255*2;
{совмещение начала области значений функции с начальным
адресом хеш-таблицы (a=1)}
f:=(f*10000) div (255*4);
{совмещение конца области значений функции с конечным адресом
хеш-таблицы (a=10 000)}
hash:=f
end;
Метод двоеного хеширования
Теоретическая часть
Описание метода
Двойное хеширование — метод борьбы с коллизиями, возникающими при открытой адресации, основанный на использовании двух хеш-функций для построения различных последовательностей исследования хеш-таблицы
Характеристики метода
При
двойном хешировании используются две
независимые хеш-функции
и
.
Пусть
—
это наш ключ,
—
размер нашей таблицы,
—
остаток от деления
на
,
тогда сначала исследуется ячейка с
адресом
,
если она уже занята, то рассматривается
,
затем
и
так далее. В общем случае идёт проверка
последовательности ячеек
где
Таким
образом, операции вставки, удаления и
поиска в лучшем случае выполняются
за
,
в худшем — за
,
что не отличается от обычного линейного
разрешения коллизий.
Однако в среднем, при грамотном выборе
хеш-функций, двойное хеширование будет
выдавать лучшие результаты, за счёт
того, что вероятность совпадения значений
сразу двух независимых хеш-функций
ниже, чем одной.
Пример
Показана хеш-таблица размером 13 ячеек, в которой используются вспомогательные функции:
Мы
хотим вставить ключ 14. Изначально
.
Тогда
.
Но ячейка с индексом 1 занята, поэтому
увеличиваем
на
1 и пересчитываем значение хеш-функции.
Делаем так, пока не дойдем до пустой
ячейки. При
получаем
.
Ячейка с номером 9 свободна, значит
записываем туда наш ключ.
Таким
образом, основная особенность двойного
хеширования состоит в том, что при
различных
пара
дает
различные последовательности ячеек
для исследования.
Визуализация метода
Заключение
Таким образом, основная особенность двойного хеширования состоит в том, что при различных пара дает различные последовательности ячеек для исследования.
Реализация метода на С
Вставка
add(item)
x = h1(item.key)
y = h2(item.key)
for (i = 0; i < m; i++)
if table[x] == null
table[x] = item
return
x = (x + y) mod m
table.resize() //ошибка, требуется увеличить размер таблицы
Поиск
search(key)
x = h1(key)
y = h2(key)
for (i = 0; i < m; i++)
if table[x] != null
if table[x].key == key
return table[x]
else
return null
x = (x + y) mod m
return null