6.3. Хеширование 6.3.1. Понятие хэш-таблицы и хешфункции. Коллизии и их разрешение. Идея этого метода состоит в отыскании функциональной зависимости k=f(x), которая бы позволяла за не зависящие от длины входа время (т.е. за 1 шаг) вычислить адрес блока, в котором физически находится искомая запись со значением искомого поля, равном x. Но в такой постановке задача в общем случае неразрешима. Поэтому приходиться воспользоваться хэш-таблицей. Хэш-таблица представляет из себя массив hash, такой что hash[m]=k, если k - адрес блока, в котором хранится запись со значением поискового поля, равным x, а m=h(x), где h(x) - некоторая функция, вычисляемая за 1 шаг, и называемая хэш-функцией. Тогда алгоритм хэширования выглядит так: m:=h(x); k:=hash[m]; Конечно, перед тем как выполнять поиск, следует сформировать хэш-таблицу: for x £ {ммножеств поисковых значений} do hash[h(x)]:= block(x) ; // block(x) - блок, где находится запись со значением поискового поля, равным x. Однако, на практике построение такого алгоритма возможно только при условии, что функция h - биекция, т.е. A) " x,y[(h(x) = h(y)) ® (x = y)] — условие инъективности B) " m£ {m}$xh(x) = m — условие сюръективности Очевидно, что условие B эквивалентно условию С: C) " xh(x) = ^n^^m} = 1..n) Мощность области значений функции h(x) совпадает с мощностью её определений. Следует попытаться добиться выполнения условий A и С. Но это в общем случае невозможно. Чем же грозит невыполнение этих условий? Если нарушается условие «A», то существуют две различные записи со значениями поисковых полей x и у такими, что h(x)=h(y)=m. Пусть k и l - адреса блоков, где хранятся эти записи. Тогда hash[m]=k и hash[m]=l, что реализовать напрямую невозможно. Такая ситуация называется коллизией. Последствия невыполнения условия C менее серьезны, они приводят к увеличению памяти, требуемой на хранение хэш-таблицы. В принципе на это можно пойти, если увеличение не будет слишком чрезмерным. Однако даже добиться только выполнения условия A в общем случае не представляется возможным, поэтому на практике приходится использовать специальные приемы для разрешения коллизий. Очевидно, что они зависят от выбора функции h(x). Путем всестороннего теоретического и практического исследования проблемы установлено, что оптимальная функция хеширования для целочисленных полей h(x)=x mod q + 1, где q - наименьшее простое число среди >=n2. Тогда 1<=h(x)<=n2. Если x - не числовое значение, то сначала вычисляется каким-либо способом числовое значение, и оно уже применяется в хеш-функции. Для разрешения коллизий используются различные методы, такие как метод цепочек, методы линейных и квадратичных проб и т.д. Одним из недостатков хеширования является трудность поиска по неключевым полям, так как в этом случае неизбежны естественные коллизии.
|