Использование хеша. Алгоритмы хеширования - простое объяснение сложного
Нередко при скачивании торрентов или непосредственно самих файлов в описании стоит что-то наподобие «ad33e486d0578a892b8vbd8b19e28754» (например, в ex.ua), нередко с припиской «md5». Это хеш-код - результат, который выдает хэш-функция после обработки входящих данных. В переводе с английского хэш обозначает путаницу, марихуану, травку или блюдо из мелко нарезанного мяса и овощей. очень и очень сложно, можно сказать, что практически невозможно. Тогда возникает вопрос: «Зачем вообще нужны все эти они выдают непонятную абракадабру, которая еще и не поддается расшифровке?». Об этом и пойдет речь в данной статье.
Что такое хэш-функция и как она действует?
Данная функция предназначена для преобразования входящих данных сколь угодно большого размера в результат фиксированной длины. Сам процесс такого преобразования называется хешированием, а результат - хэшем или хэш-кодом. Порой еще используют слова «отпечаток» или «дайджест сообщения», но на практике они встречаются намного реже. Существует масса различных алгоритмов того, как можно превратить любой массив данных в некую последовательность символов определенной длины. Наибольшее распространение получил алгоритм под названием md5, который был разработан еще в 1991 году. Несмотря на то, что на сегодняшний день md5 является несколько устаревшим и к использованию не рекомендуется, он до сих пор все еще в ходу и часто вместо слова «хеш-код», на сайтах просто пишут md5 и указывают сам код.
Зачем нужна хеш-функция?
Зная результат, практически невозможно определить исходные данные, но одни и те же входящие данные дают одинаковый итог. Поэтому хэш-функция (ее еще называют функция свертки) часто используется для хранения очень важной информации, такой как пароль, логин, номер удостоверения и другая персональная информация. Вместо сравнивания сведений, вводимых пользователем, с теми, которые хранятся в базе данных, происходит сопоставление их хешей. Это дает гарантию, что при случайной утечке информации никто не сможет воспользоваться важными данными для своих целей. Путем сравнения хеш-кода также удобно проверять правильность загрузки файлов с интернета, особенно если во время скачивания происходили перебои связи.
Хэш-функции: какими они бываю т
В зависимости от своего предназначения хэш-функция может быть одного из трех типов:
1. Функция для проверки целостности информации
Когда происходит по сети, происходит расчет хэша пакета, и этот результат также передается вместе с файлом. При приеме снова вычисляется хэш-код и сравнивается с полученным по сети значением. Если код не совпадает, то это говорит об ошибках, и испорченный пакет снова будет передан. У такой функции быстрая скорость расчета, но малое количество хэш значений и плохая стабильность. Пример такого типа: CRC32, у которой всего лишь 232 отличающихся между собой значения.
2. Криптографическая функция
Используется для защиты от (НД). Они позволяют проверить, не произошло ли искажение данных в результате НД во время передачи файлов по сети. Истинный хэш в этом случае общедоступен, а хэш полученного файла можно вычислить с помощью множества разных программ. У таких функций долгий и стабильный срок работы, а поиск коллизий (возможных совпадений результата от разных исходных данных) очень осложнен. Именно такие функции используют для хранения в БД паролей (SH1, SH2, MD5) и прочей ценной информации.
3. Функция, предназначенная для создания эффективной структуры данных
Ее целью является компактная и довольно упорядоченная организация сведений в специальной структуре, которая носит название хэш-таблицы. Такая таблица позволяет добавлять новую информацию, удалять сведения и выполнять поиск нужных данных с очень высокой скоростью.
Что такое хеш? Хеш-функцией называется математическое преобразование информации в короткую, определенной длины строку.
Зачем это нужно? Анализ при помощи хеш-функций часто используют для контроля целостности важных файлов операционной системы, важных программ, важных данных. Контроль может производиться как по необходимости, так и на регулярной основе.
Как это делается? Вначале определяют, целостность каких файлов нужно контролировать. Для каждого файла производится вычисления значения его хеша по специальному алгоритму с сохранением результата. Через необходимое время производится аналогичный расчет и сравниваются результаты. Если значения отличаются, значит информация содержащаяся в файле была изменена.
Какими характеристиками должна обладать хеш-функция?
- должна уметь выполнять преобразования данных произвольной длины в фиксированную;
- должна иметь открытый алгоритм, чтобы можно было исследовать её криптостойкость;
- должна быть односторонней, то есть не должно быть математической возможности по результату определить исходные данные;
- должна «сопротивляться» коллизиям, то есть не должна выдавать одинаковых значений при разных входных данных;
- не должна требовать больших вычислительных ресурсов;
- при малейшем изменении входных данных результат должен существенно изменяться.
Какие популярные алгоритмы хеширования? В настоящее время используются следующие хеш-функции:
- CRC – циклический избыточный код или контрольная сумма. Алгоритм весьма прост, имеет большое количество вариаций в зависимости от необходимой выходной длины. Не является криптографическим!
- MD 5 – очень популярный алгоритм. Как и его предыдущая версия MD 4 является криптографической функцией. Размер хеша 128 бит.
- SHA -1 – также очень популярная криптографическаяфункция. Размер хеша 160 бит.
- ГОСТ Р 34.11-94 – российский криптографический стандарт вычисления хеш-функции. Размер хеша 256 бит.
Когда эти алгоритмы может использовать системный администратор? Часто при скачивании какого-либо контента, например программ с сайта производителя, музыки, фильмов или другой информации присутствует значение контрольных сумм, вычисленных по определенному алгоритму. Из соображений безопасности после скачивания необходимо провести самостоятельное вычисление хеш-функции и сравнить значение с тем, что указано на сайте или в приложении к файлу. Делали ли вы когда-нибудь такое?
Чем удобнее рассчитывать хеш? Сейчас существует большое количество подобных утилит как платных, так и свободных для использования. Мне лично понравилась HashTab . Во-первых, утилита при установке встраивается в виде вкладки в свойства файлов, во-вторых, позволяет выбирать большое количество алгоритмов хеширования, а в третьих является бесплатной для частного некоммерческого использования.
Что есть российского? Как было сказано выше в России есть стандарт хеширования ГОСТ Р 34.11-94, который повсеместно используется многими производителями средств защиты информации. Одним из таких средств является программа фиксации и контроля исходного состояния программного комплекса «ФИКС». Эта программа является средством контроля эффективности применения СЗИ.
ФИКС (версия 2.0.1) для Windows 9x/NT/2000/XP
- Вычисление контрольных сумм заданных файлов по одному из 5 реализованных алгоритмов.
- Фиксация и последующий контроль исходного состояния программного комплекса.
- Сравнение версий программного комплекса.
- Фиксация и контроль каталогов.
- Контроль изменений в заданных файлах (каталогах).
- Формирование отчетов в форматах TXT, HTML, SV.
- Изделие имеет сертификат ФСТЭК по НДВ 3 № 913 до 01 июня 2013 г.
А как на счет ЭЦП? Результат вычисленияхеш-функции вместе с секретным ключом пользователя попадает на вход криптографического алгоритма, где и рассчитывается электронно-цифровая подпись. Строго говоря, хеш-функция не является частью алгоритма ЭЦП, но часто это делается специально, для того, чтобы исключить атаку с использованием открытого ключа.
В настоящее время многие приложения электронной коммерции позволяют хранить секретный ключ пользователя в закрытой области токена (ruToken , eToken ) без технической возможности извлечения его оттуда. Сам токен имеет весьма ограниченную область памяти, измеряемую в килобайтах. Для подписания документа нет никакой возможности передать документ в сам токен, а вот передать хеш документа в токен и на выходе получить ЭЦП очень просто.
Хеширование - это специальный метод адресации данных (некоторый алгоритм расстановки) по их уникальным ключам ( key ) для быстрого поиска нужной информации..
Базовые понятия
Хеш-таблица
Хеш-таблица представляет собой обычный массив со специальной адресацией, задаваемой некоторой функцией (Хеш-функция).
Хеш-функция
Функция, которая преобразует ключ элемента данных в некоторый индекс в таблице (хеш-таблица ), называетсяфункцией хеширования илихеш-функцией :
i = h (key );
где key - преобразуемый ключ,i - получаемый индекс таблицы, т.е. ключ отображается во множестве, например, целых чисел (хеш-адреса ), которые впоследствии используются для доступа к данным.
Хеширование таким образом – это способ, который подразумевает использование значения ключа для определения его позиции в специальной таблице..
Однако функция расстановки может для нескольких уникальных значений ключа давать одинаковое значение позицииi в хеш-таблице. Ситуация, при которой два или более ключа получают один и тот же индекс (хеш-адрес) называетсяколлизией (конфликтом) при хешировании.. Поэтому схема хеширования должна включатьалгоритм разрешения конфликтов , определяющий порядок действий, если позицияi =h (key ) оказывается уже занятой записью с другим ключом.
Имеется множество схем хеширования, различающихся и используемой хешфункцией h (key ) и алгоритмами разрешения конфликтов.
Наиболее распространенный метод задания хеш-функции: Метод деления.
Исходными данными являются: - некоторый целый ключ key и размер таблицыm . Результатом данной функции является остаток от деления этого ключа на размер таблицы. Общий вид такой функции на языке программирования С/С++:
int h (int key , int m ) {
Для m = 10 хеш-функция возвращает младшую цифру ключа.
Для m= 100 хеш-функция возвращает две младших цифры ключа.
В рассмотренных примерах хеш-функция i =h (key ) только определяет позицию, начиная с которой нужно искать (или первоначально - поместить в таблицу) запись с ключомkey . Далее необходимо воспользоваться какой – либо схемой (алгоритмом) хеширования.
Схемы хеширования
В большинстве задач два и более ключей хешируются одинаково, но они не могут занимать в хеш-таблице одну и ту же ячейку. Существуют два возможных варианта: либо найти для нового ключа другую позицию, либо создать для каждого индекса хеш-таблицы отдельный список, в который помещаются все ключи, отображающиеся в этот индекс.
Эти варианты и представляют собой две классические схемы хеширования:
хеширование методом открытой адресацией с линейным опробыванием - linear probe open addressing .
хеширование методом цепочек (со списками), или так называемое, многомерное хеширование - chaining with separate lists ;
Метод открытой адресацией с линейным опробыванием . Изначально все ячейки хеш-таблицы, которая является обычным одномерным массивом, помечены как не занятые. Поэтому при добавлении нового ключа проверяется, занята ли данная ячейка. Если ячейка занята, то алгоритм осуществляет осмотр по кругу до тех пор, пока не найдется свободное место («открытый адрес»).
Т.е. элементы с однородными ключами размещают вблизи полученного индекса.
В дальнейшем, осуществляя поиск, сначала находят по ключу позицию i в таблице, и, если ключ не совпадает, то последующий поиск осуществляется в соответствии с алгоритмом разрешения конфликтов, начиная с позицииi . .
Метод цепочек является доминирующей стратегией. В этом случаеi , полученной из выбранной хеш-функциейh (key )=i , трактуется как индекс в хеш-таблице списков, т.е. сначала ключkey очередной записи отображается на позициюi = h (key ) таблицы. Если позиция свободна, то в нее размещается элемент с ключомkey , если же она занята, то отрабатывается алгоритм разрешения конфликтов, в результате которого такие ключи помещаются в список, начинающийся вi -той ячейке хеш-таблицы. Например
В итоге имеем таблицу массива связных списков или деревьев.
Процесс заполнения (считывания) хеш-таблицы прост, но доступ к элементам требует выполнения следующих операций:
Вычисление индекса i ;
Поиск в соответствующей цепочке.
Для улучшения поиска при добавлении нового элемента можно использовать алгоритма вставки не в конец списка, а - с упорядочиванием, т.е. добавлять элемент в нужное место.
Пример реализации метода прямой адресации с линейным опробыванием . Исходными данными являются 7 записей (для простоты информационная часть состоит только из целочисленных данных), объявленного структурного типа:
int key; // Ключ
int info; // Информация
{59,1}, {70,3}, {96,5}, {81,7}, {13,8}, {41,2}, {79,9}; размер хеш-таблицы m=10.
Хеш-функцияi =h (data ) =data .key %10; т.е. остаток от деления на 10 -i .
На основании исходных данных последовательно заполняем хеш-таблицу.
Хеширование первых пяти ключей дает различные индексы (хеш-адреса):
Первая коллизия возникает между ключами 81 и 41 - место с индексом 1 занято. Поэтому просматриваем хеш-таблицу с целью поиска ближайшего свободного места, в данном случае - это i = 2.
Следующий ключ 79 также порождает коллизию: позиция 9 уже занята. Эффективность алгоритма резко падает, т.к. для поиска свободного места понадобилось 6 проб (сравнений), свободным оказался индекс i = 4.
Общее число проб такого метода от1 до n-1 пробы на элемент, гдеn- размер хеш-таблицы..
Реализация метода цепочек для предыдущего примера. Объявляем структурный тип для элемента списка (однонаправленного):
int key; // Ключ
int info; // Информация
zap*Next; // Указатель на следующий элемент в списке
На основании исходных данных последовательно заполняем хеш-таблицу, добавляя новый элемент в конец списка, если место уже занято.
Хеширование первых пяти ключей, как и в предыдущем случае, дает различные индексы (хеш-адреса): 9, 0, 6, 1, и 3.
При возникновении коллизии, новый элемент добавляется в конец списка. Поэтому элемент с ключом 41, помещается после элемента с ключом 81, а элемент с ключом 79 - после элемента с ключом 59.
Индивидуальные задания
1. Бинарные деревья. Используя программу датчик случайных чисел получить 10 значений от 1 до 99 и построить бинарное дерево.
Сделать обход:
1.а Обход слева направо: Left-Root-Right: сначала посещаем левое поддерево, затем - корень и, наконец, правое поддерево.
(Или наоборот, справа налево: Right -Root- Left)
1.б Обход сверху вниз: Root-Left-Right: посещаем корень до поддеревьев.
1.в Обход снизу вверх: Left-Right-Root: посещаем корень после поддеревьев
В рамках данной статьи, я расскажу вам что такое Хэш , зачем он нужен, где и как применяется, а так же наиболее известные примеры.
Многие задачи в области информационных технологий весьма критичны к объемам данных. Например, если нужно сравнить между собой два файла размером по 1 Кб и два файла по 10 Гб, то это совершенно разное время. Поэтому алгоритмы, позволяющие оперировать более короткими и емкими значениями, считаются весьма востребованными.
Одной из таких технологий является Хэширование, которое нашло свое применение при решении массы задач. Но, думаю вам, как обычному пользователю, все еще непонятно, что же это за зверь такой и для чего он нужен. Поэтому далее я постараюсь объяснить все наиболее простыми словами.
Примечание : Материал рассчитан на обычных пользователей и не содержит многих технических аспектов, однако для базового ознакомления его более, чем достаточно.
Что такое Хэш или Хэширование?
Начну с терминов.
Хэш-функция, Функция свертки - это специального вида функция, которая позволяет преобразовывать произвольной длины тексты к коду фиксированной длины (обычно, короткая цифро-буквенная запись).
Хэширование - это сам процесс преобразования исходных текстов.
Хэш, Хеш-код, Значение Хэш, Хэш-сумма - это выходное значение Хэш-функции, то есть полученный блок фиксированный длины.
Как видите, у терминов несколько образное описание, из которого сложно понять для чего это все нужно. Поэтому сразу приведу небольшой пример (об остальных применениях расскажу чуть позже). Допустим, у вас есть 2 файла размером 10 Гб. Как можно быстро узнать какой из них нужный? Можно использовать имя файла, но его легко переименовать. Можно смотреть даты, но после копирования файлов даты могут быть одинаковыми или в иной последовательности. Размер, как сами понимаете, мало чем может помочь (особенно, если размеры совпадают или вы не смотрели точные значения байтов).
Вот тут-то и нужен этот самый Хэш, который представляет собой короткий блок, формирующийся из исходного текста файла. У этих двух файлов по 10 Гб будет два разных, но коротких Хэш-кода (что-то вроде "ACCAC43535" и "BBB3232A42"). Используя их, можно будет быстро узнать нужный файл, даже после копирования и смены имен.
Примечание : В связи с тем, что Хэш в компьютером мире и в интернете весьма известное понятие, то нередко все то, что имеет отношение к Хэшу, сокращают до этого самого слова. Например, фраза "у меня используется Хэш MD5" в переводе означает, что на сайте или где-то еще используется алгоритм хэширования стандарта MD5.
Свойства Хеш-функций
Теперь, расскажу о свойствах Хэш-функций, чтобы вам было легче понять где применяется и для чего нужно Хэширование. Но, сначала еще одно определение.
Коллизия - это ситуация, когда для двух разных текстов получается одна и та же Хэш-сумма. Как сами понимаете, раз блок фиксированной длины, то он имеет ограниченное число возможных значений, а следовательно возможны повторы.
А теперь к самим свойствам Хэш-функций:
1. На вход может подаваться текст любого размера, а на выходе получается блок данных фиксированной длины. Это следует из определения.
2. Хэш-сумма одних и тех же текстов должна быть одинаковой. В противном случае, такие функции просто бесполезны - это аналогично случайному числу.
3. Хорошая функция свертки должна иметь хорошее распределение. Согласитесь, что если размер выходного Хэша, к примеру, 16 байт, то если функция возвращает всего 3 разных значения для любых текстов, то толку от такой функции и этих 16 байт никакого (16 байт это 2^128 вариантов, что примерно равно 3,4 * 10^38 степени).
4. Как хорошо функция реагирует на малейшие изменения в исходном тексте. Простой пример. Поменяли 1 букву в файле размером 10 Гб, значение функции должно стать другим. Если же это не так, то применять такую функцию весьма проблематично.
5. Вероятность возникновения коллизии. Весьма сложный параметр, рассчитываемый при определенных условиях. Но, суть его в том, что какой смысл от Хэш-функции, если полученная Хэш-сумма будет часто совпадать.
6. Скорость вычисления Хэша. Какой толк от функции свертки, если она будет долго вычисляться? Никакой, ведь тогда проще данные файлов сравнивать или использовать иной подход.
7. Сложность восстановления исходных данных из значения Хэша. Эта характеристика больше специфическая, нежели общая, так как не везде требуется подобное. Однако, для наиболее известных алгоритмов эта характеристика оценивается. Например, исходный файл вы вряд ли сможете получить из этой функции. Однако, если имеет место проблема коллизий (к примеру, нужно найти любой текст, который соответствует такому Хэшу), то такая характеристика может быть важной. Например, пароли, но о них чуть позже.
8. Открыт или закрыт исходный код такой функции. Если код не является открытым, то сложность восстановления данных, а именно криптостойкость, остается под вопросом. Отчасти, это проблема как с шифрованием .
Вот теперь можно переходить к вопросу "а для чего это все?".
Зачем нужен Хэш?
Основные цели у Хэш-функций всего три (вернее их предназначения).
1. Проверка целостности данных. В данном случае все просто, такая функция должна вычисляться быстро и позволять так же быстро проверить, что, к примеру, скачанный из интернета файл не был поврежден во время передачи.
2. Рост скорости поиска данных. Фиксированный размер блока позволяет получить немало преимуществ в решении задач поиска. В данном случае, речь идет о том, что, чисто технически, использование Хэш-функций может положительно сказываться на производительности. Для таких функций весьма важное значение представляют вероятность возникновения коллизий и хорошее распределение.
3. Для криптографических нужд. Данный вид функций свертки применяется в тех областях безопасности, где важно чтобы результаты сложно было подменить или где необходимо максимально усложнить задачу получения полезной информации из Хэша.
Где и как применяется Хэш?
Как вы, вероятно, уже догадались Хэш применяется при решении очень многих задач. Вот несколько из них:
1. Пароли обычно хранятся не в открытом виде, а в виде Хэш-сумм, что позволяет обеспечить более высокую степень безопасности. Ведь даже если злоумышленник получит доступ к такой БД, ему еще придется немало времени потратить, чтобы подобрать к этим Хэш-кодам соответствующие тексты. Вот тут и важна характеристика "сложность восстановления исходных данных из значений Хэша".
Примечание : Советую ознакомиться со статьей пара советов для повышения уровня безопасности паролей .
2. В программировании, включая базы данных. Конечно же, чаще всего речь идет о структурах данных, позволяющих осуществлять быстрый поиск. Чисто технический аспект.
3. При передачи данных по сети (включая Интернет). Многие протоколы, такие как TCP/IP, включают в себя специальные проверочные поля, содержащие Хэш-сумму исходного сообщения, чтобы если где-то произошел сбой, то это не повлияло на передачу данных.
4. Для различных алгоритмов, связанных с безопасностью. Например, Хэш применяется в электронных цифровых подписях.
5. Для проверки целостности файлов. Если обращали внимание, то нередко в интернете можно встретить у файлов (к примеру, архивы) дополнительные описания с Хэш-кодом. Эта мера применяется не только для того, чтобы вы случайно не запустили файл, который повредился при скачивании из Интернета, но и бывают просто сбои на хостингах . В таких случаях, можно быстро проверить Хэш и если требуется, то перезалить файл.
6. Иногда, Хэш-функции применяются для создания уникальных идентификаторов (как часть). Например, при сохранении картинок или просто файлов, обычно используют Хэш в именах совместно с датой и временем. Это позволяет не перезаписывать файлы с одинаковыми именами.
На самом деле, чем дальше, тем чаще Хэш-функции применяются в информационных технологиях. В основном из-за того, что объемы данных и мощности самых простых компьютеров сильно возрасли. В первом случае, речь больше о поиске, а во втором речь больше о вопросах безопасности.
Известные Хэш-функции
Самыми известными считаются следующие три Хэш-функции.
Хэш-таблицы
Хэш-таблица (перемешанная таблица, таблица с вычисляемыми адресами) – это динамическое множество, поддерживающее операции добавления, поиска и удаления элемента и использующее специальные методы адресации .
Основное отличие таблиц от других динамических множеств – вычисление адреса элемента по значению ключа.
Идея хэш-реализации состоит в том, что работа с одним большим массивом сводится к работе с некоторым количеством небольших множеств.
Например, записная книжка. Страницы книжки помечены буквами. Страница, помеченная некоторой буквой, содержит фамилии, начинающиеся с этой буквы. Большое множество фамилий разбито на 28 подмножеств. При поиске книжка сразу открывается на нужной букве и поиск ускоряется.
В программировании хэш-таблица - это структура данных, которая хранит пары (ключ или индекс + значение) и с которой выполняются три операции: добавление новой пары, поиск и удаление пары по ключу.
Поиск в хэш-таблицах осуществляется в два этапа:
первый шаг – вычисление хэш-функции, которая преобразует ключ поиска в табличный адрес :
второй шаг – процесс разрешения конфликтов при обработке таких ключей.
Если разным значениям ключей таблицы хэш-функция генерирует одинаковые адреса, то говорят, что возникает коллизия (конфликт, столкновение).
Хэш-функции
Основное назначение хэш-функции - поставить в соответствие различным ключам по возможности разные не отрицательные целые числа.
Хэш-функция тем лучше , чем меньше одинаковых значений она генерирует.
Хэш-функцию надо подобрать таким образом, чтобы выполнялись следующие свойства:
хэш-функция определена на элементах множества и принимает целые неотрицательные значения;
хэш-функцию легко вычислить ;
хэш-функция может принимать различные значения приблизительно с равной вероятностью (минимизация коллизий);
на близких значениях аргумента хэш-функция принимает далекие друг от друга значения.
Чтобы построить хорошую хэш-функцию надо знать распределение ключей. Если распределение ключей известно, то в идеальном случае, случае плотность распределения ключей и плотность распределения значений хэш-функции должны быть идентичны.
Пусть p ( key ) - плотность распределения запросов ключей. Тогда в идеальном случае плотность распределения запросов входов таблицыg ( H ( key )) д. быть такой, чтобы в среднем число элементов, кот. надо пройти в цепочках близнецов, было минимальным.
Пример .
Пусть имеется множество ключей
{0, 1, 4, 5, 6, 7, 8, 9, 15, 20, 30, 40}
и пусть таблица допускает 4 входа.
Можно построить хэш-функцию:
h (key ) = key % 4 .
Тогда получатся следующие адреса для входов
{0, 1, 2, 3} таблицы:
h (key ) |
Номер входа | ||||
Максимальная длина цепочки | ||||
% обращений | ||||
3·0,5+1,5·0,25+0,5·0,08+1·0,17 ≈ 2,1 элемента списка.
Пример с другой хэш-функцией.
h (key ) |
Номер входа | ||||
% обращений |
В среднем потребуется пройти 4·1,5·0,25 = 1,5 элемента списка.
Если это информационно-поисковая система, то повысится ее производительность при поиске примерно на 25%.
Методы построения хэш-функций
Модульное хэширование
Простой, эффективный и часто используемый метод хэширования.
Размер таблицы выбирается в виде простого числа m и вычисляется хэш-функция как остаток от деления :
h (key ) = key % m
key – целое числовое значение ключа,
m - число хэш-значений (входов хэш-таблицы).
Такая функция называется модульной и изменяется от 0 до (m - 1 ).
Модульная хэш-функция на языке С++:
typedef int HashIndexType ;
HashIndexType Hash (int Key )
{ return Key % m ; }
Пример
key = {1, 3, 56, 4, 32, 40, 23, 7, 41,13, 6,7}
Пусть m = 5
h (key ) = {1, 3, 1, 4, 2, 0, 3, 2, 1, 3, 1, 2}
Важен выбор m .Чтобы получить случайное распределение ключей надо брать простое число.
Мультипликативный метод
Хэш-функция:
h(key) =
0 < A < 1 – константа.
12 mod 5 = 2 (остаток от деления 12 на 5).
5,04 mod1 = 0,04 (выделяется дробная часть)
Пример
key = 123456
m = 10000
A = 0,6180339887499 = 0,618…
h (key ) = =
Аддитивный метод
Используется для строк переменной длины (размер таблицы m равен 256).
{ HashIndexType h = 0;
while (*str)
h += (*str)++;
return h ;
Недостаток аддитивного метода: не различаются схожие слова и анаграммы, т.е. h (XY ) = h (YX )
Аддитивный метод , в котором ключом является символьная строка. В хеш-функции строка преобразуется в целое суммированием всех символов и возвращается остаток от деления на m (обычно размер таблицы m = 256).int h(char *key, int m) {int s = 0;while(*key)s += *key++;return s % m;}Коллизии возникают в строках, состоящих из одинакового набора символов, например, abc и cab .Данный метод можно несколько модифицировать, получая результат, суммируя только первый и последний символы строки-ключа.int h(char *key, int m) {int len = strlen(key), s = 0;if(len < 2) // Если длина ключа равна 0 или 1,s = key; // возвратить keyelse s = key + key;return s % m;}В этом случае коллизии будут возникать только в строках, например, abc и amc .
хеш-функция принимает ключ и вычисляет по нему адрес в таблице (адресом может быть индекс в массиве, к которому прикреплены цепочки), то есть она, например, из строки "abcd" может получить число 3, а из строки "efgh" может получить число 7 а потом первая структура цепочки берётся через hash, или через hash дальше идёт поиск по цепочке, пока в цепочке структур из hash не будет найдено "abcd", или в цепочке структур из hash не будет найдено "efgh" когда структура с "abcd" найдена, берутся и возвращаются остальные её данные, или она вообще вся возвращается (адрес её), чтобы можно было остальные данные из неё взять а цепочка структур создаётся потому, что многие разные ключи, имеют один и тот же адрес в таблице, то есть, например, хеш-функция для "abcd" может выдать 3 и для "zxf9" тоже может выдать 3, таким образом они сцепляются в цепочку, которая повисает на третьем индексе массива......
В массиве H хранятся сами пары ключ-значение. Алгоритм вставки элемента проверяет ячейки массива H в некотором порядке до тех пор, пока не будет найдена первая свободная ячейка, в которую и будет записан новый элемент.
Алгоритм поиска просматривает ячейки хеш-таблицы в том же самом порядке, что и при вставке, до тех пор, пока не найдется либо элемент с искомым ключом, либо свободная ячейка (что означает отсутствие элемента в хеш-таблице).
Исключающее ИЛИ
Используется для строк переменной длины. Метод аналогичен аддитивному, но различает схожие слова. Заключается в том, что к элементам строки последовательно применяется операция «исключающее ИЛИ»
typedef unsigned char HashIndexType;
unsigned char Rand8;
HashIndexType Hash(char *str)
{ unsigned char h = 0;
while (*str) h = Rand8;
return h ; }
Здесь Rand 8 – таблица из 256 восьмибитовых случайных чисел.
размер таблицы <= 65536
typedef unsigned short int HashIndexType;
unsigned char Rand8;
HashIndexType Hash(char *str)
{ HashIndexType h; unsigned char h1, h2;
if (*str == 0) return 0;
h1 = *str; h2 = *str + 1; str++;
while (*str)
{ h1 = Rand8; h2 = Rand8;
str++; }
h = ((HashIndexType)h1 << 8) | (HashIndexType)h2;
return h % HashTableSize }
Универсальное хэширование
Подразумевает случайный выбор хэш-функции из некоторого множества во время выполнения программы.
Если в мультипликативном методе использовать в качестве А последовательность случайных значений вместо фиксированного числа, то получится универсальная хэш-функция.
Однако время на генерирование случайных чисел будет слишком большим .
Можно использовать псевдослучайные числа.
// генератор псевдослучайных чисел
typedef int HashIndexType;
HashIndexType Hash(char *v, int m)
{ int h, a = 31415, b = 27183;
for(h = 0; *v != 0 ; v++, a = a*b % (m - l))
h = (a*h + *v) % m;
return (h < 0) ? (h + m) : h;