11

I know that deque is more efficient than vector when insertions are at front or end and vector is better if we have to do pointer arithmetic. But which one to use when we have to perform insertions in middle.? and Why.?

user1543957
  • 1,758
  • 4
  • 20
  • 30
  • 4
    Deque may not be more efficient, especially if there are only a small number of elements. – James McNellis Sep 14 '12 at 14:39
  • For relatively small collections of cheap to copy objects, `vector` beats the other containers hands down, regardless of the operations. (I've measured `vector` vs. `deque` for a FIFO with a maximum of 12 characters, and although `deque` is optimized for this utilization, `vector` was significantly faster on the machine I tested.) – James Kanze Sep 14 '12 at 15:58
  • Just a nuance: I find it odd that a double-ended queue would allow enqueuing operations in the middle... The strictest implementation of a queue would only allow for insertion into the back and removal at the front. – FriskySaga Oct 05 '20 at 00:32

4 Answers4

13

You might think that a deque would have the advantage, because it stores the data broken up into blocks. However to implement operator[] in constant time requires all those blocks to be the same size. Inserting or deleting an element in the middle still requires shifting all the values on one side or the other, same as a vector. Since the vector is simpler and has better locality for caching, it should come out ahead.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
3

Selection criteria with Standard library containers is, You select a container depending upon:

  1. Type of data you want to store &
  2. The type of operations you want to perform on the data.

If you want to perform large number of insertions in the middle you are much better off using a std::list.

If the choice is just between a std::deque and std::vector then there are a number of factors to consider:

  • Typically, there is one more indirection in case of deque to access the elements, so element access and iterator movement of deques are usually a bit slower.
  • In systems that have size limitations for blocks of memory, a deque might contain more elements because it uses more than one block of memory. Thus, max_size() might be larger for deques.
  • Deques provide no support to control the capacity and the moment of reallocation. In particular, any insertion or deletion of elements other than at the beginning or end invalidates all pointers, references, and iterators that refer to elements of the deque. However, reallocation may perform better than for vectors, because according to their typical internal structure, deques don't have to copy all elements on reallocation.
  • Blocks of memory might get freed when they are no longer used, so the memory size of a deque might shrink (this is not a condition imposed by standard but most implementations do)
Alok Save
  • 202,538
  • 53
  • 430
  • 533
  • 4
    This isn't as evident as it might seem. On modern architectures, `std::list` is very inefficient, in general, because of its poor locality, and if the contents are cheap to copy, it can be faster to insert into the middle of a `vector`, despite the copy. – James Kanze Sep 14 '12 at 15:49
  • 1
    Also, the internal structure of `deque` does require it copy all of the elements on at least one side of the insertion, if the insertion isn't at the end. (More generally, one can say that `vector` requires shifting all of the elements after the insertion, and `deque` requires shifting either all of the elements after or all of the elements before.) – James Kanze Sep 14 '12 at 15:51
1

std::deque could perform better for large containers because it is typically implemented as a linked sequence of contiguous data blocks, as opposed to the single block used in an std::vector. So an insertion in the middle would result in less data being copied from one place to another, and potentially less reallocations.

Of course, whether that matters or not depends on the size of the containers and the cost of copying the elements stored. With C++11 move semantics, the cost of the latter is less important. But in the end, the only way of knowing is profiling with a realistic application.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • I concur, but it should be noted that the contiguous data blocks in paragraph 1 are logical, not physical. The OP should research the physical layout more to fully understand the ramifications of mid-inserts – WhozCraig Sep 14 '12 at 14:48
  • As pointed out in my comment to Doug T.'s answer, this is false. If you're inserting close to the beginning, `deque` _could_ choose to shift only the elements before the insertion, thus shifting less than `vector`. I don't know if any implementations actually do this, however, and at any rate, it must shift _all_ of the elements on one side of the insertion, either before or after. – James Kanze Sep 14 '12 at 15:56
  • @JamesKanze maybe I phrased my answer poorly. I have no disagreement with what you say. My point is that *all* of the elements to move is more likely to be a smaller number for a ""deque"" than for a ""vector"". – juanchopanza Sep 14 '12 at 16:45
0

Deque would still be more efficient, as it doesn't have to move half of the array every time you insert an element.

Of course, this will only really matter if you consider large numbers of elements, and even than it is advisable to run a benchmark and see which one works better in your particular case. Remember that premature optimization is the root of all evil.

Qnan
  • 3,714
  • 18
  • 15
  • Unless you're inserting at one of the ends, `deque` will require shifting some of the elements: either all before the insertion, or all after the insertion. – James Kanze Sep 14 '12 at 15:52
  • @JamesKanze true, but usually only a limited number of them will have to be moved. I'm pretty sure it won't be a half of all the elements as in the case of vector. – Qnan Sep 14 '12 at 18:34