Подтвердить что ты не робот

Какой самый быстрый контейнер STL для поиска?

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

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

В моей текущей реализации есть два std::vectors для элементов каждой таблицы. Класс предоставляет как доступ ко всему вектору, так и удобные методы для поиска конкретного элемента данных таблицы через std::find, std::find_if и т.д.

Кто-нибудь знает, предпочтительнее ли использовать std::list, std::set или std::map над std::vector для поиска? В большинстве случаев это будет запрашиваться в этих контейнерах после однократного заполнения базы данных при создании нового соединения.

Я также открыт для использования функций С++ 0x, поддерживаемых VS2010 или Boost.

4b9b3361

Ответ 1

Для поиска определенного значения с std::set и std::map требуется время O (log N), а с двумя другими - время O (N); Таким образом, std::set или std::map, вероятно, лучше. Поскольку у вас есть доступ к С++ 0x, вы также можете использовать std::unordered_set или std::unordered_map, которые в среднем занимают постоянное время.

Для find_if, между ними мало различий, потому что он принимает произвольный предикат, и контейнеры, конечно, не могут оптимизировать произвольно.

Однако, если вы часто вызываете find_if с определенным предикатом, вы можете оптимизировать себя: используйте std::map или std::set с помощью специального компаратора или специальных ключей и вместо этого используйте find.

Ответ 2

Сортированный вектор с использованием std::lower_bound может быть таким же быстрым, как std::set, если вы не обновляетесь очень часто; они оба O (log n). Стоит попытаться понять, что лучше для вашей собственной ситуации.

Ответ 3

Поскольку из ваших (расширенных) требований вам нужно искать по нескольким полям, я бы указал вам на Boost.MultiIndex.

Эта библиотека Boost позволяет создавать один контейнер (только с одним образцом каждого из его элементов) и индексировать его по произвольному числу индексов. Он также позволяет точно определить, какие индексы использовать.

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

Я бы порекомендовал отсортированный индекс (например, skip-list, если возможно) для размещения запросов диапазона (все имена, начинающиеся с Abc?), если разница в производительности либо незаметна, либо просто не имеет значения.

Ответ 4

Если вы хотите искать только отдельные значения, один столбец в таблице, то std::hash является самым быстрым.

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

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

Ответ 5

Протестируйте его. Это очень легко, контейнеры почти взаимозаменяемы в STL.

Ответ 6

Не stl, но коммерческий контейнер С++ является контейнером abax, который имеет O (1) в поиске, удалении, изменении, O (logn) во вставке.

Ответ 7

Не сам ответ, но обязательно используйте typedef для обозначения типа контейнера, который вы используете, что-то вроде typedef std::vector< itemtype > data_table_cache; Затем используйте свой тип typedef везде.