Monthly Archives: July 2014

The power of <algorithm>

Have you seen the presentation by Bjarne Stroustrup Why you should avoid Linked Lists? This presentation has received lots of popularity from many programmers even though the example Bjarne used to compare the performance of linked lists and vectors was quite misleading

He planned to show that vectors are better than linked lists even in scenarios that most programmers think are better suited for linked lists. The problem is, that in his example, the asymptotic complexity is the same when using the linked list or when using the vector. I don’t think any competent programmer would even consider using linked list in that case. He would probably use some kind of binary search tree which would dominate the performance as shown in another response to the presentation.

On Bjarne’s defense, he did correctly mention that the problem in his example is the linear search. The problem is that many people ignore it and jump to wrong conclusions like: Arrays are good, all other fancy containers are bad, and that is all because of cache.

In this post, I wanted to show an example where linked lists dominate arrays to demonstrate that they are not useless at all. The example is simply the following task, which might be quite common in real life: Remove all odd integers from a sequence.

This can be solved quite easily by the following code which is quite ordinary:

For linked lists this code has complexity of O(n) because we already have the iterator for the element we are erasing and do not have to perform linear-search for every element as in Bjarne’s example. For vectors the complexity is O(n^2) because we need to shift all of the following elements after every erase we perform.

Benchmarking on my computer shows an expected decisive victory of linked lists now.

This clearly shows that linked lists are not useless. As with everything, you just need to use them in a right situation. In this case we already have an iterator inside the list so we can perform item insertion or removal in constant time. Of course, in real life we do not have only linked lists and vectors. It is true that for most tasks std::deque would outperform linked lists. Pure linked lists have really niche applications. As an example, they can possibly outperform std::deque when the items are huge.

Now comes the gotcha and the main point of this post. There exists another way how to perform this task and that is by using the standard library:

After benchmarking this the results may seem surprising to you:

As you can see the vector is now slightly faster than the linked list. How can it be? Where did the complexity go? The answer is that the std::remove_if is a bit more clever than our approach above and the complexity for vector is again O(n).

The lesson from this is that you should really, really look at the <algorithm> library and, instead of imperfectly reinventing wheels, try to use it when you can.

The following is the whole code I used for benchmarking: