Что такое хеш-таблицы и хеш-карты и их типичные варианты использования? - PullRequest
34 голосов
/ 26 сентября 2008

Я недавно сталкивался с этими терминами несколько раз, но я совершенно запутался, как они работают и когда они обычно применяются?

Ответы [ 4 ]

67 голосов
/ 26 сентября 2008

Ну, подумай об этом так.

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

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

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

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

Каждый элемент имеет два свойства, данные и ключ, который идентифицирует данные. Например, список почтовых индексов США будет представлять собой почтовый индекс -> имя типа ассоциации. Функция уменьшает клавишу, но не учитывает данные.

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

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

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

Типичная хеш-таблица не имеет бесконечного числа элементов, доступных для хранения, поэтому это число обычно уменьшается до индекса, который соответствует размеру массива. Один из способов сделать это - просто взять модуль индекса по сравнению с размером массива. Для массива размером 10 индекс 0-9 будет отображаться непосредственно в индекс, а индекс 10-19 снова будет отображаться в 0-9 и т. Д.

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

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

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

Функция, которая уменьшает ключ до числа, не выдает линейное значение, т.е. «AAA» становится 1, затем «AAB» становится 2, поэтому хэш-таблица не сортируется по типичным значениям.

На эту тему также есть хорошая статья в Википедии, здесь .

50 голосов
/ 26 сентября 2008

lassevk ответ очень хороший, но может содержать слишком много деталей. Вот резюме. Я намеренно опускаю определенную релевантную информацию, которую вы можете спокойно игнорировать в 99% случаев.

Существует без существенных различий между хеш-таблицами и хеш-картами в 99% случаев.

Хеш-таблицы являются волшебными

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

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

2) Если вы что-то делаете одним ключом на хеш-таблице, это невероятно быстро . Это означает, что put(key,value), get(key), contains(key) и remove(key) все очень быстрые.

3) Общие хеш-таблицы не в состоянии делать что-либо, не перечисленное в # 2 ! (Под «неудачей» мы подразумеваем, что они невероятно медленные.)

Когда мы используем хеш-таблицы?

Мы используем хеш-таблицы , когда их магия соответствует нашей проблеме.

Например, кэширование часто заканчивается использованием хеш-таблицы - например, допустим, у нас 45 000 студентов в университете, и некоторым процессам необходимо хранить записи для всех них. Если вы регулярно обращаетесь к учащемуся по идентификационному номеру, тогда кеш ID => student имеет смысл. Оптимизируемая операция для этого кэша: быстрый поиск .

Хэши также необычайно полезны для хранения отношений между данными , когда вы не хотите использовать всю сложность и изменять сами объекты. Например, во время регистрации на курс может быть хорошей идеей связать студентов с классами, которые они посещают. Однако по какой-то причине вы можете не захотеть, чтобы объект Student знал об этом. Используйте хэш studentToClassRegistration и храните его, пока вы делаете все, что вам нужно.

Они также делают довольно хорошим первым выбором для структуры данных , за исключением случаев, когда вам нужно выполнить одно из следующих действий:

Когда не использовать хеш-таблицы

Перебирать элементы . Хеш-таблицы обычно не выполняют итерацию очень хорошо. (То есть универсальные. Конкретные реализации иногда содержат связанные списки, которые используются для того, чтобы итерация по ним меньше отстой. Например, в Java LinkedHashMap позволяет быстро перебирать ключи или значения.)

Сортировка. Если вы не можете выполнить итерацию, сортировка - это тоже королевская боль.

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

4 голосов
/ 26 сентября 2008

если вы говорите с точки зрения Java, оба являются коллекциями, которые позволяют добавлять, удалять и обновлять объекты и использовать алгоритмы Hasing для внутреннего использования.

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

Помимо синхронизации, внутренний механизм для хранения и извлечения объектов хешируется в обоих случаях.

Если вам нужно посмотреть, как работает хеширование, я бы порекомендовал немного погуглить на Data Structers и методах хеширования.

0 голосов
/ 26 сентября 2008

Hashtables / hashmaps связывают значение (называемое «ключом» для устранения неоднозначности) с другим значением. Вы можете рассматривать их как словарь (слово: определение) или запись в базе данных (ключ: данные).

...