0

vector is the first choice in many situations because random access is O(1), as there are not many containers that are fast enough, or at least O(log(n)).

My issue with vector being that vector<>::erase() is O(n), map<>::erase() is faster and is a better container.

An alternative would be to use an object pool, but it is not a standard container, and implementations might vary depending on use, so I'm not very keen on using something I don't really understand or know a lot about.

It seems map is a very good alternative to vector<> when there is often-occurring deletions, but I wanted to know if there are better alternatives to it.

So is there a container that is both fast with random access and deletion?

Is there an usual way to make an object pool?

jokoon
  • 6,207
  • 11
  • 48
  • 85
  • 2
    Have you considered unordered collections? – W.F. Nov 10 '17 at 22:16
  • 13
    Have you profiled your code to determine if this is really an issue? – Dúthomhas Nov 10 '17 at 22:18
  • Have you considered `std::list`? – Thomas Matthews Nov 10 '17 at 22:21
  • 8
    Are your vectors ordered - that is, elements sorted in any way? If _not_ then swap the element-to-be-deleted with the last element, then erase the last element. That's constant time. – davidbak Nov 10 '17 at 22:21
  • 1
    Never underestimate how expensive that one iteration in O(1) can be if done wrong. The beauty of `std::vector` is you have to work at getting it wrong, and this often makes up for the occasional O(n). If you are primarily removing elements from the beginning or end, consider using `std::deque`. If removal is random, well... Measure the alternatives and don't be surprised if `std::vector` still wins overall. – user4581301 Nov 10 '17 at 22:38
  • 3
    `O(1)` doesn't necessarily mean fast, it means constant time. So `O(1)` vs `O(n)` could mean 1 hour vs n seconds. Which one is faster? – Bo Persson Nov 10 '17 at 23:49

1 Answers1

4

What alternative to C++ vector when it comes to fast deletion?

Erasing the last element of a vector (i.e. pop operation) has constant complexity, so if you don't need to keep your sequence ordered, then an efficient solution is to swap the target element with the last one, and pop it.

A linked list has constant complexity deletion that maintains the order of the sequence, but indexed lookup is linear (i.e not random access).


The (unordered) map sure has both asymptotically efficient lookup and erase, but you won't get the same behaviour as a vector would have. If you create an index -> element map, and remove element from index i, then there will be a gap between i - 1 and i + 1, while the vector would shift the elements at indices greater than i left.

The indexable skip list has logarithmic (on average; worst case is linear) lookup and deletion. However, there is no implementation of it in the standard library.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • @DaleWilson yeah, I went by the title without paying enough attention to the content. The answer mentions that drawback now. – eerorika Nov 10 '17 at 22:24
  • That's a very good point, actually you can't really make a replacement for `vector::erase()` with a map. – alain Nov 10 '17 at 22:34