Исполняющая структура Хаскелла.

Я пишу программу, которая много ищет таблицы. Таким образом, я изучал документацию Haskell, когда я наткнулся на Data.Map (конечно), но также Data.HashMap и Data.Hashtable. Я не эксперт по алгоритмам хеширования, и после проверки пакетов все они кажутся очень похожими. Поэтому мне было интересно:

1: каковы основные отличия, если таковые имеются?

2: что было бы наиболее эффективным с большим объемом поиска на картах/таблицах из ~ 4000 пар ключ-значение?

Ответ 1

1: Каковы основные отличия, если они есть?

  • Data.Map.Map является сбалансированным двоичным деревом внутри, поэтому его временная сложность для поиска - O (log n). Я считаю, что это " persistent" структура данных, что означает, что она реализована так, что мутационные операции дают новую копию только с соответствующими частями структуры обновлены.
  • Data.HashMap.Map является внутренним элементом Data.IntMap.IntMap, который, в свою очередь, реализуется как дерево Патрисии; его временной сложностью для поиска является O (min (n, W)), где W - количество бит в целых числах. Он также "настойчив".
  • Data.HashTable.HashTable - фактическая хеш-таблица с временной сложностью O (1) для поиска. Тем не менее, это изменяемая структура данных - операции выполняются на месте - поэтому вы застряли в монаде IO, если хотите ее использовать.

2: что было бы наиболее эффективным с большим объемом поиска на картах/таблицах из ~ 4000 пар ключ-значение?

Лучший ответ, который я могу вам дать, к сожалению, - "это зависит". Если вы берете асимптотические сложности буквально, вы получаете O (log 4000) = около 12 для Data.Map, O (min (4000, 64)) = 64 для Data.HashMap и O (1) = 1 для Data.HashTable. Но на самом деле это не так. Вы должны попробовать их в контексте вашего кода.

Ответ 2

Очевидное различие между Data.Map и Data.HashMap заключается в том, что для первого нужны ключи в Ord, последние Hashable ключи. Большинство общих ключей - оба, так что это не решающий критерий. У меня нет никакого опыта с Data.HashTable, поэтому я не могу прокомментировать это.

API-интерфейсы Data.HashMap и Data.Map очень похожи, но Data.Map экспортирует больше функций, некоторые, например, alter отсутствуют в Data.HashMap, другие предоставляются в строгих и нестрогих вариантах, тогда как Data.HashMap (я предполагаю, что вы имели в виду hashmap из unordered-containers) предоставляет ленивые и строгие API в отдельных модулях. Если вы используете только общую часть API, переключение действительно безболезненно.

Что касается производительности, Data.HashMap unordered-containers имеет довольно быстрый поиск, последний измеренный, он был явно быстрее, чем Data.IntMap или Data.Map, который выполняется, в частности, для (еще не выпущенной) ветки HAMT unordered-containers. Я думаю, что для вставок он был более или менее наравне с Data.IntMap и несколько быстрее, чем Data.Map, но я немного расплывчатый.

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

Ответ 3

Data.HashTable Документация теперь говорит: "Используйте hashtables package". Там хорошая запись в блоге, объясняющая, почему hashtables - хороший пакет здесь. Он использует монаду ST.