Динамическое кодирование строк переменной длины
111
Для хранения кодовой таблицы можно использовать массив,
элементами которого является запись, содержащая три поля: код
последовательности РREFIX + CHARACTER (переменная code_value), код
префикса (рrefix_code) и код символа расширения (aррend_character). Так
например, строка ente с кодом 264 в Табл.5.2 при длине кодовой
комбинации 12 бит занимает в памяти 6 байт, а при записи в Табл.5.6 в
виде 262е — 3 байта. Очевидно, что с увеличением длины строк
эффективность такого способа хранения повышается.
Уменьшение времени поиска строки в кодовой таблице может быть
достигнуто применением метода непосредственного доступа к таблице,
который получил название "хеширование". Идея хеширования состоит в
том, чтобы взять некоторые характеристики ключа поиска Кey и
использовать полученную частичную информацию в качестве основы
поиска. Hад ключом производятся некоторые математические операции и
затем вычисленная хеш-функция h(Key), используемая в качестве адреса
начала поиска. Hаходить вид подходящей хеш-функции довольно сложно,
так как для большого числа простых преобразований ключей имеет место
явление, при котором для различных ключей получается одна и та же хеш-
функция, то есть h(Key
i
) = h(Key
j
) при Key
i
Key
j
. Такое явление получило
название "коллизия". Для разрешения коллизий разработаны различные
методы, о которых будет сказано ниже.
Хорошая хеш-функция должна удовлетворять двум требованиям:
а) ее вычисление должно быть очень быстрым;
б) она должна вызывать минимальное число коллизий.
Свойство а) в большой степени зависит от характеристик вычислителя и
вида хеш-функции, а свойство б)-от характеристик данных. Если бы ключи
были случайными величинами, то можно было бы просто выделить группу
битов и использовать их для хеш-функции. Hо на практике, чтобы
удовлетворить б) почти всегда нужна функция, зависящая от всех битов.
Следует заметить, что существует большое количество различных методов
хеширования, но ни один из них не оказался предпочтительнее простых
схем деления и умножения.
При методе деления используется остаток от деления на число М:
h(Key) = Key mod M . (5.4 )
Здесь важную роль играет выбор числа М. Рекомендации по выбору числа
М приведены в [11]. Особо эффективной оказывается процедура деления,
основанная на алгебраической теории кодирования [21,22]. В качестве
делителя в этом случае вместо целого числа М используется неприводимый
многочлен Р(х) вида: