При выполнении просмотра в структуре данных Hash, почему это быстрая операция? - PullRequest
0 голосов
/ 03 ноября 2011

Когда вы выполняете поиск в Hashtable, ключ преобразуется в хеш. Теперь, используя это хэшированное значение, оно напрямую отображается в ячейку памяти или есть дополнительные шаги?

Просто пытаюсь понять вещи немного под одеялом.

А какие еще есть структуры поиска данных на основе ключей и почему они медленнее хеша?

Ответы [ 3 ]

2 голосов
/ 03 ноября 2011

Хеш-таблицы не обязательно быстрые. Люди считают хеш-таблицы «быстрой» структурой данных, потому что время извлечения не зависит от количества записей в таблице. То есть извлечение из хеш-таблицы является «O (1)» (константа время) операция.

Время получения из других структур данных может варьироваться в зависимости от количества записей на карте. Например, для сбалансированного двоичного дерева время поиска масштабируется с логарифмом base-2 его размера; это "O (log n)".

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

1 голос
/ 03 ноября 2011

A Хэш (он же Hash Table) подразумевает более чем Карта (или Ассоциативный массив) .

В частности, Карта (или Ассоциативный массив) является Абстрактным типом данных :

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

В то время как Хеш-таблица является реализацией Карты (хотя ее также можно считать ADT, которая включает «стоимость»):

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

Таким образом, это утечка деталей реализации: HashMap - это Map, который использует алгоритм хеш-таблицы и, таким образом, обеспечивает ожидаемые характеристики производительности такого алгоритма. «Утечка» деталей реализации хороша в этом случае, потому что она обеспечивает некоторые основные [ожидаемые] связанные гарантии, такие как [ожидаемое] O(1) - или постоянное время - get.

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

Другой формой карты является Список ассоциаций (или «alist», который является распространенным в программировании LISP). Хотя списки ассоциаций O(n) для get, они могут иметь гораздо меньше накладных расходов для малых n, что поднимает еще одну точку: Big-Oh описывает ограничение поведения (как n -> infinity) и не касается относительной производительности для конкретного [smallish] n:

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

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

Удачного кодирования.


Вот источник для реализации HashMap, которая есть в OpenJDK 7. Изучение метода put показывает, что это простая цепочка в качестве метода разрешения конфликтов и что базовый «массив блоков» будет увеличиваться в 2 раза при каждом изменении размера (которое срабатывает при достижении коэффициента нагрузки). Коэффициент нагрузки и ожидаемая амортизированная производительность, в том числе используемая функция хеширования, описаны в документации класса.

0 голосов
/ 03 ноября 2011

«Основанный на ключе» подразумевает отображение некоторого вида. Вы можете реализовать один в связанном списке или массиве, и он, вероятно, будет довольно медленным (O (n)) для поиска или удаления.

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

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

Если вы начнете преодолевать определенный порог коллизий, большинство реализаций увеличит размер хеш-таблицы, что также займет еще одно O (n) время. Однако в среднем это будет происходить не чаще, чем через каждые 1 / n вставок. Итак, мы амортизировали постоянное время.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...