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

Имеет ли стандартная библиотека С++ набор, упорядоченный по порядку вставки?

Имеется ли в стандартной библиотеке С++ "упорядоченный набор" datastructure? По упорядоченному набору я имею в виду то, что в точности совпадает с обычным std::set, но помнит порядок, в который вы добавили элементы к нему.

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

4b9b3361

Ответ 1

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

Лучший, чистый подход мог бы быть чем-то вроде Boost.MultiIndex, который позволяет добавлять несколько индексов или "взгляды" на контейнер, поэтому вы можете иметь последовательный и упорядоченный индекс.

Ответ 2

Вместо того, чтобы создавать std:: set любого типа, который вы используете, почему бы не передать ему std:: пару объекта и индекс, который увеличивается при каждой вставке?

Ответ 3

Нет, это не так.

Такой контейнер, по-видимому, должен был бы иметь два разных итератора, один для итерации в порядке, определяемом порядком добавления, а другой для итерации в обычном порядке set. Там нет ничего подобного в стандартных библиотеках.

Один из вариантов имитации заключается в том, чтобы иметь set какого-либо типа, который содержит навязчивый связанный список node в дополнение к фактическим данным, которые вас волнуют. После добавления элемента в set добавьте его в связанный список. Прежде чем удалить элемент из set, удалите его из связанного списка. Это гарантировано, так как указатели на установочные элементы не являются недействительными с помощью любой операции, кроме удаления этого элемента.

Ответ 4

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

Ответ 5

[Отказ от ответственности: я дал аналогичный ответ на этот похожий вопрос уже]

Если вы можете использовать Boost, очень простым решением будет использование библиотеки Boost.Bimap только для заголовков (двунаправленные карты).

Рассмотрим следующий пример программы, которая отображает несколько фиктивных записей в порядке вставки (попробуйте здесь):

#include <iostream>
#include <string>
#include <type_traits>
#include <boost/bimap.hpp>

using namespace std::string_literals;

template <typename T>
void insertByOrder(boost::bimap<T, size_t>& mymap, const T& element) {
  using pos = typename std::remove_reference<decltype(mymap)>::type::value_type;
  // We use size() as index, therefore indexing the elements with 0, 1, ...
  mymap.insert(pos(element, mymap.size()));
}

int main() {
  boost::bimap<std::string, size_t> mymap;

  insertByOrder(mymap, "stack"s);
  insertByOrder(mymap, "overflow"s);

  // Iterate over right map view (integers) in sorted order
  for (const auto& rit : mymap.right) {
    std::cout << rit.first << " -> " << rit.second << std::endl;
  }
}

Псевдоним напуганного типа в insertByOrder() необходим для вставки элементов в boost::bimap в следующей строке (см. boost::bimap документацию).

Ответ 6

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