Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
find8_1.doc
Скачиваний:
37
Добавлен:
12.03.2015
Размер:
3.46 Mб
Скачать

4.4. Хеширование

Одним из основных недостатков последовательного поиска является зависимость времени доступа к различным элементам множества . Как упоминалось выше, основной причиной этого является отсутствие структурированности множества. С другой стороны массив является структурой, позволяющей, организовать прямой доступ к элементу при наличии его индекса. Но поскольку поиск обычно ведется по значению элемента, возникает задача преобразования значения элемента в индекс его местонахождения. Выше было описано, как с такой задачей справляются деревья поиска. Эта задача может быть решена при помощи специальных таблиц, преобразующих значения элементов в индексы, но тогда надо уметь решать задачу поиска в этих таблицах, и образуется заколдованный круг. Промежуточным вариантом является индексно-последовательный доступ, когда множествопредставляется в виде набора подмножеств и существует функция отображающая значение каждого элемента изв номер подмножества его содержащего. При такой организации множества, поиск элемента может быть сведен к поиску соответствующего подмножества с дальнейшим перебором в некотором порядке его элементов.

4.4.1. Открытое хеширование. Одной из реализаций такой идеи является таблица, строкам которой приписаны подмножества множества. Множества элементов, приписанных различным строкам таблицы, не пересекаются и каждый элемент множествапринадлежит некоторой строке. Пусть строки таблицы пронумерованы и номера лежат в интервале от 0 до. ПоложимПусть далее задана некоторая функция14, которая называется функцией хеширования. Решение задачи поискасводится к вычислению значенияс дальнейшей проверкой предикатадля элементов соответствующей строки. Наиболее часто используемой структурой для представления элементов строкиявляется последовательный список или массив. Сочетание прямого и последовательного доступа представляет определенный компромисс между временем и объемом памяти. При этом число подмножеств множестваявляется параметром алгоритма хеширования, выбор которого позволяет поддерживать необходимое соотношение между показателями времени и объема памяти.

Ниже приведен пример хеш-таблицы, в которой подмножества заданы списками:

Временная сложность одной операции поиска в худшем случае выражается как сумма , где первый член суммы является временем вычисления значения, а второй член временем поиска элементав строке. Поскольку в неудачном случае, все элементы могут попасть в один класс, то временная сложность поиска в худшем случае составляет, где- число элементов множества15. Понятно, что минимизация общего времени поиска связана с минимизацией каждого слагаемого суммы. Посколькупрямо пропорционально числу элементов множества, то хорошие алгоритмы хеширования должны минимизировать мощность. Гораздо больший интерес представляет среднее время поиска. Средняя стоимость поиска зависит от того, насколько равномерно распределены хеш-значения по позициям таблицы. Оказывается при выполнении некоторых предположений (а именно если каждый элемент может равновероятно попасть в любую изпозиций таблицы) можно оценить среднее время поиска элемента в таблице. Числоназывается коэффициентом заполнения таблицы. Пусть имеется хеш-функция равномерно распределяющая элементы множествапо строкам таблицы. Тогда верна

Теорема [4] При равномерном хешировании среднее время успешного поиска в хеш-таблице с цепочками равно .

При этом при выполнении некоторых естественных условий среднее время можно свести к .

Поскольку два разных элемента ипопадают в одну строку таблицы в случае, то следуя [14] назовем такую ситуацию коллизией. Поскольку разрешение коллизий требует дополнительного времени, при выборе подходящей хеш-функции руководствуются требованиями:

1. для любого время вычислениядолжно быть небольшим;

2. число коллизий должно быть минимальным.

Выбор подходящей функции, удовлетворяющей этим условиям, является достаточно сложной задачей. Подбор функции хеширования во многом зависит от элементов множества . При условии, что ключевые параметры элементов множествиописываются натуральными числами, можно положить. Такая функция дает достаточно неплохие результаты при простых значениях. Еслиявляется множеством строк, то в качестве функции хеширования можно рассмотреть функцию, задаваемую процедурой

Function h(a: string): 0..d-1;

Var i, sum : integer;

begin

sum:=0;

for i=0 to length(a) do

sum:=sum+ord(a[i]);

h:=sum mod d;

end

Функция суммирует коды букв из строки с последующим вычислением остатка по модулю простого числа. Однако, как показывает анализ, это неудачный пример функции хеширования. В самом деле, еслисостоит из строк, начинающихся с одинаковых префиксов и имеющих одинаковые суффиксы, например строк вида str1+nom+str2, где nom – цифровая строка от нуля до, то распределение значений функциибудет крайне неравномерным. Значения функциизаполнят только около трети значений множества. Объясняется это тем, что константные части строк (str1 и str2) не влияют на число различных значений функции, а только производят сдвиг этих значений внутри, а сумма цифр чисел от 0 допринимает ограниченное число значений.

Для достижения равномерности можно использовать алгоритмы порождения равномерно распределенных псевдослучайных чисел [14, т.2]. В частности, в [7] предлагается использовать следующую функцию: Пусть не является степенью числа 10, элементы исходного множества определяются числами из интервала. Пустьтакое число, чтопримерно равно. Положим, где- целая часть числа. Для символьных строк можно рассматривать представление строки в позиционной системе счисления с основанием 256, где каждому символу строки сопоставляется его двоичный код. Тогда в качестве значенияможно выбрать значение числа в системе счисления с основанием 256. Например, строке 'abcd' соответствует числопри.

4.4.2. Закрытое хеширование. При открытом хешировании для разрешения коллизий используются списки, содержащие элементы множества, и массив указателей на них. Рассмотрим другой вариант представления данных, когда все элементы множествахранятся в едином массиве, а при вставке элемента для разрешения коллизий применяется методика повторного хеширования. Если мы пытаемся поместить элементв позицию массива, которая занята другим элементом, то выбирается последовательность индексов,и так далее, пока не будет найдена свободная позиция. Последовательность функций хешированияфиксируется заранее и не меняется в ходе работы алгоритма. Одним из наиболее простых способов определения последовательностиявляется соотношениепри фиксированном. Такой вариант построения последовательности называется линейным хешированием. Поиск элементав таблице заключается в последовательном вычислении значений, пока не будет найдено это значение или не встретится незаполненная ячейка массива, которая является меткой конца подпоследовательности, в которой может встретиться элемент. Допустим при, необходимо вставить элемент, а соответствующая позиция массива содержит другой элемент:

0

1

Первой свободной ячейкой в этом случае будет ячейка с адресом , куда и вставляется элемент. После вставки элемента таблица выглядит следующим образом:

0

1

Предложенная схема хорошо работает при последовательности операций вставки и поиска, но операция удаления элементов из таблицы создает определенные проблемы. Если понимать удаление элемента из таблицы как очистку соответствующего элемента массива, то такая операция может разбить последовательность, в которой находился соответствующий элемент на две и вторая последовательность становится недоступной при поиске . Например, удаление элементаиз таблицы разобьет последовательность, начинающуюся с индексаи содержащую не менее трех элементов на две с начальными индексамии. Если удаляемый элемент не очищать, а помечать подходящим способом так, чтобы он не разрывал существующие последовательности адресов, то приведенный выше алгоритм поиска может быть использован и при операциях удаления элементов из таблицы [7].

При закрытом хешировании элементы входной последовательности могут оказаться размещенными с помощью разных хеш-функций. Поскольку конец последовательности подбора хеш-функции определяется незаполненным элементом массива, то при выборе хеш-функции необходимо добиваться, чтобы метки концов были как можно более равномерно распределены по массиву. Возникает вопрос, какова должна быть в среднем длина последовательности при включении в таблицу элемента? В [7] приводится анализ этой ситуации. При условии, что таблица имеетпозиций, из которыхячеек заполнены, и значения хеш-функции равномерно распределены, среднее число шагов поиска при линейном хешировании незанятой позиции составляет. Например вставка элемента при заполненной наполовину таблицы требует в среднем 2-х попыток. Поскольку значениеменяется от 0 до, то среднее число попыток на заполнение одной позиции при заполнениипозиций аппроксимируется функцией. В частности присреднее число попыток вставки одного элемента равно, соответственноэлементов -. При поиске элемента, которого нет в таблице, а для этого необходимо найти незаполненную позицию, требуется в среднем такое же число проб, как и при вставке нового элемента при точно таком же заполнении таблицы. Если элемент присутствует в таблице, то его поиск может закончиться как на первом, так и на втором, и нашаге, где- число заполненных позиций в таблице. Поэтому поиск требует в среднем такое же число проб, сколько необходимо для вставки всех элементов, сделанных к моменту поиска. Поскольку удаление найденного элемента требует константного времени, то среднее время на удаление совпадает со временем поиска элемента, присутствующего в таблице. Следует отметить, что удаление элемента не уменьшает среднее время поиска.

Вышеприведенный пример с последовательностью функцией показывает, что значения последовательностиимеют тенденции к группировке (возникают достаточно длинные заполненные смежные фрагменты, при наличии наборов подряд идущих незаполненных ячеек). Ситуация мало меняется при выборе последовательности, гдеудовлетворяет условию, или любой другой, где очередная проба некоторым фиксированным образом зависит от предыдущих проб. Одним из способов борьбы с этим явлением является введение случайности в определение функций. Положим, где- случайная перестановка чисел 1,2, …,. Конечно, числавыбираются один раз и не меняются в ходе работы алгоритма.

Рассмотрим пример задачи поиска , гдеи- некоторые подмножества отрезка, приведенный в [22]. Пусть имеется некотороеупорядоченное по возрастанию конечное множество чисел из интервала [0,1]. Положими, разделим отрезок [0,1] на равных частей, так что-я часть представляет интервал,. Положими. Рассмотрим характеристическую функцию,такую что, если интервалне содержит точек из, и, если. Тогда для любого запросапоиск реализуется следующим образом: Вычисляется. Номерявляется номером интервала, в котором необходимо искать точку. Если, то, в противном случае вычисляется значение предиката, и в случае его истинности получаем.

Хеш-таблицы часто применяются в базах данных, и, особенно, в языковых процессорах типа компиляторов и ассемблеров, где они используются в таблицах идентификаторов. В таких приложениях, таблица - наилучшая структура данных.

В заключение этого раздела приведем, позаимствованную из [3] сравнительную таблицу сложностей выполнения операций вставки и поиска на множестве из элементов при применении различных структур данных.

Используемая структура данных

Худший случай

В среднем

вставка

поиск

Порядковая

статистика

вставка

Удачный

поиск

Неудачный

Поиск

Неупорядоченный массив

O(1)

O(n)

O(nlogn)

O(1)

O(n/2)

O(n)

Неупорядоченный связный список

O(1)

O(n)

O(nlogn)

O(1)

O(n/2)

O(n)

Упорядоченный массив

O(n)

O(n)

O(1)

O(n/2)

O(n/2)

O(n/2)

Упорядоченный связный список

O(n)

O(n)

O(n)

O(n/2)

O(n/2)

O(n/2)

Бинарный поиск (на базе упоряд. массива)

O(n)

O(logn)

O(1)

O(n/2)

O(logn)

O(logn)

Дерево бинарного поиска

O(n)

O(n)

O(n)

O(logn)

O(logn)

O(logn)

Красно-черное дерево

O(logn)

O(logn)

O(logn)

O(logn)

O(logn)

O(logn)

АВЛ дерево

O(logn)

O(logn)

O(logn)

O(logn)

O(logn)

O(logn)

Хеширование

O(1)

O(n)

O(nlogn)

O(1)

O(1)

O(1)

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]