Согласно этой странице , я могу добиться постоянной вставки времени, если использую
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);
Я спрашиваю, потому что я пишу функцию, которая основана на контейнере.Я хочу вставить элемент (который, я знаю, самый большой) в конец любого контейнера, в который передан. Использование «Варианта А» выше имеет другое поведение для контейнера, например 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, проблема здесь в том, что C ++ 03 говорит «логарифмическая в общем случае, но амортизированная константа, если t вставляется сразу после p».в то время как C ++ 0x говорит «логарифмическая в общем случае, но амортизированная константа, если t вставляется прямо перед p.»
PS: я использую GCC 4.5 в Ubuntu 11.04 с включенной поддержкой C ++ 0x.
Редактировать: я запускал эмпирические тесты с включенной и отключенной поддержкой C ++ 0x и опубликовал результаты в ответе .По сути, вывод заключается в том, что обеспечить end()
так же хорошо (и, очевидно, безопаснее) указывать подсказку для вставки.Однако это, очевидно, только эмпирическое наблюдение.Как уже говорилось, стандарт по-прежнему сбивает с толку в этом аспекте.