Хеширование
Категория реферата: Рефераты по информатике, программированию
Теги реферата: борьба реферат, курсовые
Добавил(а) на сайт: Ермил.
Предыдущая страница реферата | 1 2 3 4 5 6 | Следующая страница реферата
. периодически менять функцию, пересчитывать все адреса. Это отнимает очень много ресурсов и выводит из строя базу на некоторое время.
Существует техника, позволяющая динамически менять размер хеш-структуры
[10]. Это – динамическое хеширование. Хеш-функция генерирует так называемый
псевдоключ (“pseudokey”), который используется лишь частично для доступа к
элементу. Другими словами, генерируется достаточно длинная битовая
последовательность, которая должна быть достаточна для адресации всех
потенциально возможных элементов. В то время, как при статическом
хешировании потребовалась бы очень большая таблица (которая обычно хранится
в оперативной памяти для ускорения доступа), здесь размер занятой памяти
прямо пропорционален количеству элементов в базе данных. Каждая запись в
таблице хранится не отдельно, а в каком-то блоке (“bucket”). Эти блоки
совпадают с физическими блоками на устройстве хранения данных. Если в блоке
нет больше места, чтобы вместить запись, то блок делится на два, а на его
место ставится указатель на два новых блока.
Задача состоит в том, чтобы построить бинарное дерево, на концах ветвей
которого были бы указатели на блоки, а навигация осуществлялась бы на
основе псевдоключа. Узлы дерева могут быть двух видов: узлы, которые
показывают на другие узлы или узлы, которые показывают на блоки. Например, пусть узел имеет такой вид, если он показывает на блок:
|Zero |Null |
|Bucket |Указатель |
|One |Null |
Если же он будет показывать на два других узла, то он будет иметь такой вид:
|Zero |Адрес a |
|Bucket |Null |
|One |Адрес b |
Вначале имеется только указатель на динамически выделенный пустой блок. При
добавлении элемента вычисляется псевдоключ, и его биты поочередно
используются для определения местоположения блока. Например (см. рисунок), элементы с псевдоключами 00… будут помещены в блок A, а 01… - в блок B.
Когда А будет переполнен, он будет разбит таким образом, что элементы 000…
и 001… будут размещены в разных блоках.
[pic]
Расширяемое хеширование (extendible hashing)
Расширяемое хеширование близко к динамическому. Этот метод также
предусматривает изменение размеров блоков по мере роста базы данных, но это
компенсируется оптимальным использованием места. Т.к. за один раз
разбивается не более одного блока, накладные расходы достаточно малы [9].
Вместо бинарного дерева расширяемое хеширование предусматривает список, элементы которого ссылаются на блоки. Сами же элементы адресуются по
некоторому количеству i битов псевдоключа (см. рис). При поиске берется i
битов псевдоключа и через список (directory) находится адрес искомого
блока. Добавление элементов производится сложнее. Сначала выполняется
процедура, аналогичная поиску. Если блок неполон, добавляется запись в него
и в базу данных. Если блок заполнен, он разбивается на два, записи
перераспределяются по описанному выше алгоритму. В этом случае возможно
увеличение числа бит, необходимых для адресации. В этом случае размер
списка удваивается и каждому вновь созданному элементу присваивается
указатель, который содержит его родитель. Таким образом, возможна ситуация, когда несколько элементов показывают на один и тот же блок. Следует
заметить, что за одну операцию вставки пересчитываются значения не более, чем одного блока. Удаление производится по такому же алгоритму, только
наоборот. Блоки, соответственно, могут быть склеены, а список – уменьшен в
два раза.
[pic]
Итак, основным достоинством расширяемого хеширования является высокая эффективность, которая не падает при увеличении размера базы данных. Кроме этого, разумно расходуется место на устройстве хранения данных, т.к. блоки выделяются только под реально существующие данные, а список указателей на блоки имеет размеры, минимально необходимые для адресации данного количества блоков. За эти преимущества разработчик расплачивается дополнительным усложнением программного кода.
Функции, сохраняющие порядок ключей (Order preserving hash functions)
Существует класс хеш-функций, которые сохраняют порядок ключей [11].
Другими словами, выполняется
K1 < K2 ( h(K1) < h(K2)
Эти функции полезны для сортировки, которая не потребует никакой
дополнительной работы. Другими словами, мы избежим множества сравнений, т.к. для того, чтобы отсортировать объекты по возрастанию достаточно просто
линейно просканировать хеш-таблицу.
В принципе, всегда можно создать такую функцию, при условии, что хеш-
таблица больше, чем пространство ключей. Однако, задача поиска правильной
хеш-функции нетривиальна. Разумеется, она очень сильно зависит от
конкретной задачи. Кроме того, подобное ограничение на хеш-функцию может
пагубно сказаться на ее производительности. Поэтому часто прибегают к
индексированию вместо поиска подобной хеш-функции, если только заранее не
известно, что операция последовательной выборки будет частой.
Минимальное идеальное хеширование
Как уже упоминалось выше, идеальная хеш-функция должна быстро работать и
минимизировать число коллизий. Назовем такую функцию идеальной (perfect
hash function) [12]. С такой функцией можно было бы не пользоваться
механизмом разрешения коллизий, т.к. каждый запрос был бы удачным. Но можно
наложить еще одно условие: хеш-функция должна заполнять хеш-таблицу без
пробелов. Такая функция будет называться минимальной идеальной хеш-
функцией. Это идеальный случай с точки зрения потребления памяти и скорости
работы. Очевидно, что поиск таких функций – очень нетривиальная задача.
Один из алгоритмов для поиска идеальных хеш-функций был предложен Р.
Чичелли [13]. Рассмотрим набор некоторых слов, для которых надо составить
минимальную идеальную хеш-функцию. Пусть это будут некоторые ключевые слова
языка С++. Пусть это будет какая-то функция, которая зависит от некоего
численного кода каждого символа, его позиции и длины. Тогда задача создания
функции сведется к созданию таблицы кодов символов, таких, чтобы функция
была минимальной и идеальной. Алгоритм очень прост, но занимает очень много
времени для работы. Производится полный перебор всех значений в таблице с
откатом назад в случае необходимости, с целью подобрать все значения так, чтобы не было коллизий. Если взять для простоты функцию, которая складывает
коды первого и последнего символа с длиной слова (да, среди слов умышленно
нет таких, которые дают коллизию), то алгоритм дает следующий результат:
|Auto |21 |Double |0 |Int |15 |Struct |23 |
|Break |28 |Else |12 |Long |26 |Switch |17 |
|Case |1 |Enum |4 |Register|18 |Typedef |29 |
|Char |2 |Extern |9 |Return |10 |Union |30 |
|Const |8 |Float |27 |Short |22 |Unsigned|24 |
|Continue|5 |For |20 |Signed |3 |Void |13 |
|Default |7 |Goto |19 |Sizeof |25 |Volatile|31 |
|Do |14 |If |16 |Static |6 |While |11 |
Подробный анализ алгоритма, а также реализацию на С++ можно найти по адресу
[12]. Там же описываются методы разрешения коллизий. К сожалению, эта тема
выходит за рамки этой работы.
Разрешение коллизий
Составление хеш-функции – это не вся работа, которую предстоит выполнить программисту, реализующему поиск на основе хеширования. Кроме этого, необходимо реализовать механизм разрешения коллизий. Как и с хеш-функциями существует несколько возможных вариантов, которые имеют свои достоинства и недостатки.
Метод цепочек
Метод цепочек – самый очевидный путь решения проблемы. В случае, когда
элемент таблицы с индексом, который вернула хеш-функция, уже занят, к нему
присоединяется связный список. Таким образом, если для нескольких различных
значений ключа возвращается одинаковое значение хеш-функции, то по этому
адресу находится указатель на связанный список, который содержит все
значения. Поиск в этом списке осуществляется простым перебором, т.к. при
грамотном выборе хеш-функции любой из списков оказывается достаточно
коротким. Но даже здесь возможна дополнительная оптимизация. Дональд Кнут
([3], стр. 558) отмечает, что возможна сортировка списков по времени
обращения к элементам. С другой стороны, для повышения быстродействия
желательны большие размеры таблицы, но это приведет к ненужной трате памяти
на заведомо пустые элементы. На рисунке ниже показана структура хеш-таблицы
и образование цепочек при возникновении коллизий.
[pic]
Прекрасная наглядная иллюстрация этой схемы разрешения коллизий в виде Java- апплета вместе с исходным кодом на C++ представлена по адресу [14].
Открытая адресация
Рекомендуем скачать другие рефераты по теме: изложение 8 класс по русскому, оформление доклада.
Предыдущая страница реферата | 1 2 3 4 5 6 | Следующая страница реферата