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

5.6.2. Выбор хеш-функций и оценка их эффективности

Вопросы выбора хеш-функции очень подробно рассмотрены в [9,14]. Авторы отмечают, что хорошая хеш-функция должна удовлетворять двум требованиям:

  • ее вычисление должно выполняться очень быстро;

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

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

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

Модульное хеширование (метод деления)

В этом случае используется уже рассмотренная выше модульная хеш-функция, основанная на вычислении остатка от деления ключа K на размер хеш-таблицы M: h(K)= K mod M.

Надо тщательно выбирать константу M, ориентируясь на характер распределения данных. В [9, 14] показано, что выбор в качестве размера таблицы степени числа 2 (M=2n) оправдан только в том случае, если входные данные достаточно равномерно распределены внутри своего диапазона значений. Тогда вычисление хеш-адеса сведется всего-навсего к тому, чтобы взять n младших бит ключа. Аналогичная ситуация и со степенью числа 10, когда хеш адрес определяется несколькими младшими десятичными цифрами ключа. В большинстве случаев реальные данные носят неслучайный характер и лучший результат получается, когда хеш-адрес определяется полным значением ключа, а не его частью.

Показано [9], что в большинстве применений наилучший результат получается, если в качестве размера таблицы M взять простое число. Есть хорошо известные простые числа. Например, числа, равные 2t-1, являются простыми при t=2,3,5,7,13,19,31 (и ни при каких других t<31). Это простые числа Мерсенне. В общем случае подбор простого числа, наиболее близкого к нужному значению, является отдельной задачей.

Мультипликативный метод

Последовательность выполняемых операций при мультикативном методе описывается несколько сложнее, чем при модульном хешировнии, однако реализуются эти операции обычно эффективно и во многих случаях обеспечивают хорошее распределение хеш-адресов. Значение ключа K умножается на константу C, которая находится в интервале [0,1], затем от произведения K*C берётся дробная часть, умножается на размер таблицы М и усекается до целого значения..В данном методе M берется равной степени двойки (M=2n), поэтому умножение на M сводится к простому сдвигу вправо на n двоичных разрядов. Единственная медленная операция — умножение на константу C, однако во многих случаях умножение реализуется эффективней, чем деление на простое число при модульном методе. В качестве константы C Кнут рекомендует золотое сечение С=(sqrt(5) - 1)/2 = 0.6180339887499.