В соответствии с эта страница, я могу добиться постоянной установки времени, если я использую
iterator std::set::insert ( iterator position, const value_type& x );
а итератор position
, который я предоставляю, непосредственно "предшествует" правильной (в порядке) точке вставки.
Теперь, если я знаю, что значение, которое я вставляю, заканчивается (поскольку оно является самым большим), например:
set<int> foo = {1, 2, 3};
foo.insert(4); // this is an inefficient insert
В соответствии с вышеприведенным критерием я должен передать последний элемент foo.end()-1
в insert
не foo.end()
. Правильно ли я понимаю? Что произойдет, если я пройду foo.end()
? Будет ли это вставка O(log n)
или O(1)
. Итак, варианты:
// Option A
foo.insert(foo.end()-1, 4);
// Option B
foo.insert(foo.end(), 4);
// Safer version of Option A
if(foo.empty())
foo.insert(4);
else
foo.insert(foo.end()-1, 4);
Я спрашиваю, потому что я пишу функцию, которая была построена на контейнере. Я хочу вставить элемент (который, как я знаю, самый большой), в конец любого контейнера, который передается. Использование "Option A" выше имеет другое поведение для контейнера, такого как vector
:
foo.insert(foo.end()-1, 4);
// result is {1, 2, 3, 4} if foo is an std::set
// result is {1, 2, 4, 3} if foo is an std::vector
Как указывает @Bo_Persson, проблема здесь в том, что С++ 03 говорит "логарифмический вообще, но амортизируется постоянным, если t вставлен сразу после p". в то время как С++ 0x говорит "логарифмический вообще, но амортизируется постоянным, если t вставлен прямо перед p."
PS: Я использую GCC 4.5 на Ubuntu 11.04 с поддержкой С++ 0x.
Изменить: я запускал эмпирические тесты с поддержкой и отключением поддержки С++ 0x, а опубликовал результаты в ответе. В основном, вывод состоит в том, что он так же хорош (и, очевидно, безопаснее), чтобы обеспечить end()
в качестве подсказки вставки. Однако это, очевидно, просто эмпирическое наблюдение. Стандарт, как указано, по-прежнему запутан в этом аспекте.