Ведение упорядоченной коллекции объектов - PullRequest
4 голосов
/ 24 января 2011

У меня есть следующие требования к коллекции объектов:

  • Динамический размер (теоретически неограниченный, но на практике пары тысяч должно быть более чем достаточно)
  • Заказано, но допускается изменение порядка и вставка в произвольных местах.
  • Позволяет удалить
  • Индексированный доступ - произвольный доступ
  • Count

Объекты, которые я храню, не большие, пара свойств и маленький или два массива (256 логических значений)

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

Ответы [ 3 ]

5 голосов
/ 24 января 2011

Оригинальный ответ: Звучит как std::list (двусвязный список) из стандартной библиотеки.

Новый ответ: После изменения спецификаций std::vector может работать, если в середине вектора не более нескольких тысяч элементов и не так много вставок и удалений. Линейная сложность вставки и удаления в середине может быть перевешена низкими константами на векторных операциях. Если вы делаете много вставок и удалений только в начале и в конце, std::deque также может сработать.

1 голос
/ 24 января 2011

-Insertion and Deletion: Это возможно для любого контейнера STL, но вопрос в том, сколько времени потребуется, чтобы сделать это.Любой контейнер связанного списка (list, map, set) будет делать это в постоянное время, в то время как контейнеры, подобные массиву (vector), будут делать это за линейное время (с постоянным амортизированным распределением).

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

-Резорт: Если вам нужно взять текущую коллекцию, отсортированную по правилу A, и применить коллекцию к правилу B, это может быть проблемой.Контейнеры, такие как map и set, параметризованы (как тип) правилом сортировки, это означает, что для его преобразования вам потребуется извлечь каждый элемент из исходной коллекции и вставить их в новую коллекцию с новым правилом сортировки.Однако, если вы используете векторный контейнер, вы можете просто использовать функцию сортировки STL в любое время, чтобы прибегнуть к какому-либо правилу.

-Random Access: вы сказали, что вам нужен произвольный доступ.Лично мое определение произвольного доступа означает, что любой элемент в коллекции может быть доступен (по индексу) за постоянное время.С этим определением (которое я считаю вполне стандартным) любая реализация связанного списка не подходит, и она оставляет вам единственную возможность использования массива-подобного контейнера (например, std :: vector).

Заключение, чтобы иметь все эти свойства, вероятно, было бы лучше использовать std :: vector и реализовать собственную сортированную вставку и отсортированное удаление (выполняя бинарный поиск в векторе, чтобы найти удаляемый элемент или место для вставки нового элемента),Если ваши объекты, которые вам нужно сохранить, имеют значительный размер, а данные, по которым они сортируются (имя, идентификатор и т. Д.), Невелики, вы можете рассмотреть возможность разделения проблемы, держа несортированный список связанных объектов (сполная информация) и сохранение отсортированного вектора ключей вместе с указателем на соответствующий узел в связанном списке (в этом случае, конечно, используйте std :: list для первого и std :: vector для второго).

Кстати, я не большой специалист по контейнерам STL, так что, возможно, я ошибся в вышесказанном, подумайте сами.Изучите STL для себя, я уверен, что вы найдете то, что вам нужно, или, по крайней мере, все, что вам нужно.Может быть, посмотрите на библиотеки Boost тоже.

1 голос
/ 24 января 2011

Вы не указали достаточно своих требований, чтобы выбрать лучший контейнер.

Динамический размер (теоретически неограниченный, но на практике пары тысяч должно быть более чем достаточно)

Контейнеры STL рассчитаны на рост по мере необходимости.

Заказано, но допускается изменение порядка и вставка в произвольных местах.

Позволяет изменить порядок? Std :: map не может быть переупорядочен: вы можете удалить из одного std :: map и вставить в другой, используя другой порядок, но в качестве разных экземпляров шаблона две переменные будут иметь разные типы. В std :: list есть функция-член sort() [спасибо Blastfurnace за указание на это], особенно эффективная для больших объектов. Std :: vector можно легко восстановить с помощью функции std::sort(), не являющейся членом, особенно эффективно для крошечных объектов.

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

Позволяет удалить

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

Индексированный доступ - произвольный доступ

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

Количество

std::list предоставляет функцию O (n) size() (так что она может обеспечить O (1) сращивания), но вы можете легко отслеживать размер самостоятельно (при условии, что вы не будете сращивать). Другие контейнеры STL уже имеют время O (1) для size().

Выводы

Подумайте, приведет ли использование std :: list к множеству неэффективных линейных поисков нужного вам элемента. Если нет, то список дает вам эффективные вставки и удаления. Курорт это хорошо.

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

Вектор позволяет осуществлять быстрый поиск и преобразование на месте, но худшая вставка / удаление. Это самый быстрый поиск с произвольным доступом с использованием индекса элемента.

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