Сложность вставки отсортированного диапазона в ассоциативный контейнер

Стандарт указывает (23.4.4.2:5 и т. д.), что построение всех четырех упорядоченных ассоциативных контейнеров (map, multimap, set, multiset) из диапазона [first, last) должно быть линейным в N = last - first, если диапазон уже отсортирован.

Однако для слияния диапазона (например, контейнера того же типа) с существующим контейнером в таблице 102 23.2.4:8 указывается только то, что insertвключение диапазона [i, j) в контейнер должно иметь сложность N log(a.size() + N), где N = distance(i, j). Казалось бы, это указывает на то, что использование вставки с подсказкой:

for (auto it = a.begin(); i != j; ++i)
    it = next(a.insert(it, *i));

может быть более эффективным, чем a.insert(i, j), имея сложность строго меньше, чем N log(a.size() + N), в зависимости от доли правильных подсказок (за исключением тривиального случая, когда N == 0); и быть линейным, поскольку каждая подсказка верна, если a изначально пусто.

Является ли это недостатком стандарта или есть какой-то другой язык (или средство), охватывающий этот случай? На практике оптимизируются ли реализации для слияния упорядоченного ассоциативного контейнера с другим?

Благодарим https://stackoverflow.com/a/11362162/567292 за то, что вдохновили на этот вопрос.


person ecatmur    schedule 06.07.2012    source источник
comment
+1 Мне было интересно то же самое, когда я прочитал вдохновляющий ответ.   -  person Andrew Durward    schedule 06.07.2012
comment
Если ответ на вашу последнюю часть — «да», то ответ на вопрос, который его вдохновляет, вероятно, заключается в использовании моего первого фрагмента кода. Что было бы неплохо, так как это также самое простое :-)   -  person Steve Jessop    schedule 06.07.2012


Ответы (1)


Я бы предположил, что в последнем случае стандарт указывает только наихудшую гарантированную производительность во время выполнения ассоциативного слияния контейнеров, оставляя на усмотрение реализации поиск более быстрых сокращений производительности, если они возможны. Имейте в виду, что, в отличие от других языков, спецификация C++ и есть спецификация. "Эталонной" реализации нет. Таким образом, можно написать реализацию, которая соответствует только определенным критериям производительности, или можно решить реализовать функции, которые превышают указанные критерии производительности. В конце концов, спецификация предназначена для того, чтобы дать вам «минимальную» гарантию производительности при реализации определенных алгоритмов.

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

person Jason    schedule 06.07.2012
comment
кроме того, построение сбалансированного дерева из отсортированного списка очень тривиально и легко. Слияния двух деревьев нет. - person Mooing Duck; 06.07.2012
comment
Потому что для каждого элемента N вы в конечном итоге дважды пересекаете дерево. - person Jason; 06.07.2012