Каковы работающие самым быстрым образом опции для незаказанного набора только для чтения уникальных строк?

Отказ от ответственности: Я понимаю, что полностью очевидный ответ на этот вопрос HashSet. Это нелепо быстро, это не заказано, и его значения уникальны.

Но я просто задаюсь вопросом, потому что HashSet изменяемый класс, таким образом, он имеет Add, Remove, и т.д.; и таким образом, я не уверен, приносит ли базовая структура данных, которая делает эти операции возможными, определенные жертвы производительности когда дело доходит до операций чтения - в частности, я обеспокоен в Contains.

В основном я задаюсь вопросом, что является абсолютными работающими самым быстрым образом существующими структурами данных, которые могут предоставить a Contains метод для объектов типа string. В или за пределами самой платформы.NET.

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

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


ОБНОВЛЕНИЕ:

Ответ идиота является превосходным примером вида вещи, которую я ищу. Trie* определенно походит на большую возможность по следующей причине: HashSet.Contains зависит от GetHashCode функция некоторых IEqualityComparer, который, насколько я могу сказать, является O (n) ** по умолчанию в.NET. Другими словами, каждый символ в строке должен быть исследован на HashSet.Contains возвратиться также true или false. Для a Trie, только возвращаемое значение true взял бы O (n) для определения; возвращаемое значение false мог потенциально возвратиться намного более быстро.

Это, конечно, гипотетически. До сих пор я не записал или столкнулся с реализацией Trie в.NET, которая может разбить a HashSet в Contains (хотя реализация, которую я записал сам, вполне приблизилась для алфавита к 'z'). Я просто говорю, это кажется возможным.

*Что ссылка, между прочим, также привела меня к другой интригующей/подобной возможности: DAWG.
** Здесь "n" относится к длине строки.

5
задан Community 23 May 2017 в 12:30
поделиться

4 ответа

Помимо вашего удивительного Hashset - это самая быстрая коллекция.

Нет более быстрого метода, потому что лежащая в основе Hashtable разрешает O (1) чтение-запись-доступ

1
ответ дан 14 December 2019 в 18:59
поделиться

Попытки хороши для выполнения Содержит , особенно для строк из конечного алфавита. Для строки s временная сложность для Contains в дереве равна O (| s |) (| s | = длина s), что является оптимальным.

2
ответ дан 14 December 2019 в 18:59
поделиться

Контейнер хеширования приближается к O (1) для вставки и извлечения, так что с точки зрения порядка вы не можете найти ничего лучше этого.

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

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

1
ответ дан 14 December 2019 в 18:59
поделиться

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

  • Плохая функция хеширования, вызывающая множество конфликтов. Худший из них приведет к вырождению поиска до O (n). У вас не будет проблем со строками, они отлично хешируют. String.GetHashCode () отлично справляется со своей задачей.
  • Коллекция, которая сильно видоизменилась с большим количеством удаленных элементов, которые были добавлены раньше. Это может привести к появлению множества пустых хэш-корзин, которые итераторы должны пропускать. Разложение до O (n) технически возможно, хотя и довольно редко.Простой обходной путь - перестроить коллекцию, переназначив ссылку (например, table = new HashSet (table);)

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

1
ответ дан 14 December 2019 в 18:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: