I always thought that in C++ standard template library (STL), a double-ended queue (deque) is a size-variable array (like a vector) with circular boundary conditions, meaning there's a head pointer i
and a tail pointer j
both pointing to some position of an array a[0..L-1]
. A push_front is i--
, a push_back is j++
, a pop_front is i++
, and a pop_back is j--
. When either pointer i
or j
reaches L
or -1
, it reappears on the other end of the array (0
and L-1
respectively). If the array size gets exhausted (pointers i==j
after insering a new element), a larger space with double the original size is reallocated to a[]
and data gets copied just like in a vector. There's also O(1)
time random access taking into account the circular boundary condition. But someone tells me that inside an STL deque there's actually a pointer array pointing to many fixed-length array segments. It's much more complicated than a circular vector. What's the benefit of not using a simple circular vector to implement the functions of a deque? Will the random access get slower?
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Why does const allow implicit conversion of refere
- thread_local variables initialization
- What uses more memory in c++? An 2 ints or 2 funct
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Selecting only the first few characters in a strin
- What exactly do pointers store? (C++)
- Converting glm::lookat matrix to quaternion and ba
- What is the correct way to declare and use a FILE
The main advantage of the
std::deque
approach is that elements once inserted in the container are never moved if you add or remove elements from either of the two ends. Thus references (and pointers) to elements are not invalidated when performing those operations (note that, quite surprisingly, iterators todeque
elements are instead invalidated when doing insertions or deletions on the ends).This, while making the implementation more complex, can be done without affecting the formal big-O complexity and makes
std::deque
a very useful container.You can have an
std::deque
of "fat" objects without having to use an extra level of indirection to avoid moving operations and maintain efficiency.23.3.8.4 [deque.modifiers] (emphasis is mine)
This is not possible with a circular-vector-like implementation.
std::deque
(double-ended queue) is an indexed sequence container that allows fast insertion and deletion at both its beginning and its end. In addition, insertion and deletion at either end of a deque never invalidates pointers or references to the rest of the elements.As opposed to
std::vector
, the elements of a deque are not stored contiguously: typical implementations use a sequence of individually allocated fixed-size arrays.The storage of a deque is automatically expanded and contracted as needed. Expansion of a deque is cheaper than the expansion of a
std::vector
because it does not involve copying of the existing elements to a new memory location.The complexity (efficiency) of common operations on deques is as follows:
Source : std::deque
As cppreference writes
This means that the large internal reallocations
std::vector
occasionally does, are not performed bystd::deque
. When space runs out, only a small fixed-size array is added. (The same but reverse happens when space becomes too large because of erasing.)Here is a small test:
On my machine, it shows deque is twice as fast as vector for this case: