Известен ли порядок итерации через std::map (и гарантирован стандартом)?
что я имею в виду - мы знаем, что сортируются в соответствии с ключами. Итак, предположим, что ключи являются целыми числами. Если я повторяю из std::map::begin()
to std::map::end()
С помощью for
, гарантирует ли стандарт, что я буду последовательно перебирать элементы с ключами, отсортированными в порядке возрастания?
пример:
std::map<int, int> map_;
map_[1] = 2;
map_[2] = 3;
map_[3] = 4;
for( std::map<int, int>::iterator iter = map_.begin();
iter != map_.end();
++iter )
{
std::cout << iter->second;
}
это гарантировано для печати 234
или это определенная реализация?
реальная причина жизни: я есть std::map
С int
ключи. В очень редких ситуациях я хотел бы перебрать все элементы с ключом, большим, чем конкретный int
значение. Да, похоже на std::vector
было бы лучшим выбором, но обратите внимание на мои "очень редкие ситуации".
редактировать: я знаю, что элементы std::map
сортируются.. нет необходимости указывать на это (для большинства ответов здесь). Я даже написал это в своем вопросе.
Я спрашивал об итераторах и порядке когда я перебираю контейнер. Спасибо @Kerrek SB за ответ.
5 ответов
Да, это гарантировано. Более того,*begin()
дает вам самый маленький и *rbegin()
самый большой элемент, как определено оператором сравнения, и два ключевых значения a
и b
для которого выражение !compare(a,b) && !compare(b,a)
справедливо считаются равными. По умолчанию используется функция сравнения std::less<K>
.
заказ не является счастливой бонусной функцией, но, скорее, это фундаментальный аспект структуры данных, так как порядок используется для определения, когда два ключа одинаковы (по выше правила) и выполнять эффективный поиск (по сути, двоичный поиск, который имеет логарифмическую сложность по количеству элементов).
это гарантируется ассоциативными требованиями к контейнерам в стандарте C++. Е. Г. увидеть 23.2.4/10 в C++11:
The fundamental property of iterators of associative containers is that they iterate through the containers in the non-descending order of keys where non-descending is defined by the comparison that was used to construct them. For any two dereferenceable iterators i and j such that distance from i to j is positive, value_comp(*j, *i) == false
и 23.2.4/11
For associative containers with unique keys the stronger condition holds, value_comp(*i, *j) != false.
я думаю, что есть путаница в структурах данных.
в большинстве языков a map
- Это просто AssociativeContainer: он сопоставляет ключ со значением. В" новых " языках это обычно достигается с помощью хэш-карты, поэтому порядок не гарантируется.
в C++, однако это не так:
-
std::map
это отсортированный ассоциативный контейнер -
std::unordered_map
- ассоциативный контейнер на основе хэш-таблицы, введенный в C++11
Итак, чтобы уточнить гарантии при заказе.
В C++03:
-
std::set
,std::multiset
,std::map
иstd::multimap
гарантированно быть приказанным согласно ключам (и поставленному критерию) - на
std::multiset
иstd::multimap
, стандарт не налагает никакой гарантии порядка на эквивалентные элементы (т. е. те, которые сравниваются равными)
In C++11:
-
std::set
,std::multiset
,std::map
иstd::multimap
гарантированно быть приказанным согласно ключам (и поставленному критерию) - на
std::multiset
иstd::multimap
стандартный предусматривает что эквивалентные элементы (те, которые сравниваются равными) упорядочены в соответствии с их порядком вставки (сначала вставлены первыми) -
std::unordered_*
контейнеры, как следует из названия, не упорядочены. Прежде всего, порядок элементов мая изменение при изменении контейнера (при вставке/удалении).
когда стандарт говорит, что элементы упорядочены таким образом, это означает, что:
- при итерации вы видите элементы в определенном порядке
- при итерации в обратном порядке вы видите элементы в обратном порядке
надеюсь, это прояснит любую путаницу.
гарантируется ли печать 234 или определена реализация?
да std::map
сортированный контейнер, приказанный Key
с предоставленным Comparator
. Так что это гарантировано.
Я хотел бы пройти итерацию через все элементы с ключом, большим, чем конкретное значение int.
это, безусловно, возможно.
да ... элементов std::map
строгий слабый заказ, это означает, что элементы будут состоять из набора (т. е., не будет никаких повторов ключей, которые "равны"), и равенство определяется тестированием на любые две клавиши A и B, что если ключ не меньше B, А B не меньше, чем a, то ключ равен ключевых Б.
это, как говорится, вы не можете правильно сортировать элементы std::map
Если слабый порядок для этого типа неоднозначен (в вашем случае, где вы используете целые числа в качестве типа ключа, это не проблема). Вы должны иметь возможность определить операцию, которая определяет общий порядок для типа, который вы используете для ключей в вашем std::map
, в противном случае у вас будет только частичный порядок для ваших элементов или poset, который имеет свойство, где A может быть не сопоставим с B. что обычно происходит в этом сценарии, так это то, что вы сможете вставить пары ключ/значение, но вы можете получить дубликаты пар ключ / значение, если вы повторите вся карта и/или обнаружение "отсутствующих" пар ключ / значение при попытке выполнить std::map::find()
определенной пары ключ / значение на карте.