Are all the inserts (anywhere) for the list constant?
What about access?
Front, back - constant time?
and in the middle of the list - linear time?
Note that, mainly due to better locality of data, in practice std::vector
is often faster than std::list
, even where in theory it should be the other way around. So the default sequential container should be std::vector
.
If you doubt, first measure whether that container is critical at all (no use in increasing the speed of a piece of code even ten times, if that piece only uses 2% of the overall time), then compare measurements with std::list
and std::deque
and make your pick.
Inserts anywhere in a std::list are constant time operations.
That said, before you can insert, you need to get an iterator to the location you'd like to insert to, which is a linear time operation unless you're talking about the front or back.
It is guaranteed by the C++ Standard 23.2.2/1:
A
list
is a kind of sequence that supports bidirectional iterators and allows constant time insert and erase operations anywhere within the sequence, with storage management handled automatically. Unlike vectors (23.2.4) and deques (23.2.1), fast random access to list elements is not supported, but many algorithms only need sequential access anyway.
Insertion of a single element into the std::list<>
takes constant time, regardless of where you insert it. Note, that std::list<>
is not an inherently ordered container, meaning that it is you who specify where exactly to insert the new element. No wonder, the time is linear.
Inserting ("splicing") a [sub]sequence of elements moved from another list into this one (i.e. std::list<>::splice
method) takes either constant time or linear time (linear in the number of element inserted). This happens because the implementation if std::list<>
has a choice of either:
(1) implementing std::list<>::size
method in constant time, and paying for it by implementing std::list<>::splice
in linear time, or
(2) implementing std::list<>::splice
method in constant time, and paying for it by implementing std::list<>::size
in linear time.
You can have either this or that, but you can't have both. The decision to follow a specific approach is up to the implementation.
http://www.sgi.com/tech/stl/List.html
A list is a doubly linked list. That is, it is a Sequence that supports both forward and backward traversal, and (amortized) constant time insertion and removal of elements at the beginning or the end, or in the middle. Lists have the important property that insertion and splicing do not invalidate iterators to list elements, and that even removal invalidates only the iterators that point to the elements that are removed
With regards to access, if you're going to search for an element somewhere in the middle, it'll take linear time. But once you've got an iterator, it'll be (of course) constant time access, and it won't be invalidated by other insertions or removals.