Home | Projects | Notes > C++ Programming > Sequence Container - std::deque
std::deque
std::dequeDeclared in the <deque> header file.
Acts like a double-ended queue.
Dynamic size
Can expand and contract as needed which is handled automatically by the STL.
Elements are NOT stored in continguous memory.
Usually, a deque is implemented as a collection of memory blocks, and these memory blocks and these memory blocks contain elements that are in a contiguous memory. However, the blocks themselves are not in contiguous memory.
A good way to think of a deque is as a linked list of vectors. So when adding an element at the front, it adds it if there's a space. If not, it will allocate a new block, add the element to that block and then link in the block. (The same happens when adding an element at the back.)
Direct element access - Constant time: O(1)
Rapid insertion and deletion at the front and back - Constant time: O(1)
Insertion or deletion of elements (elsewhere) - Linear time: O(n)
All iterators are available but may become invalid.
Iterator invalidation can occur when a std::deque changes size.
131// Initialization2std::deque<int> d1{1, 2, 3, 4, 5};3std::deque<int> d2(10, 100);    // ten 100s4
5// Initialization6std::deque<std::string> d3{7    std::string{"Kyungjae"},8    "Sunny",    // C-style string will be converted to a std::string.9    std::string{"Yena"}10};11
12// Assignment via initializer list13d1 = {2, 4, 6, 8, 10};For more information, see cppreference.com.
211std::deque<int> d1{1, 2, 3, 4, 5};2std::deque<int> d2{10, 20, 30, 40, 50};3
4std::cout << d1.size();     // 55std::cout << d1.max_size(); // A very large number6std::cout << d1.at(0);      // 1 (Supports out-of-bounds check)7std::cout << d1[1];         // 2 (Does not support out-of-bounds check)8std::cout << d1.front();    // 1 (Returns reference to the first element)9std::cout << d1.back();     // 5 (Returns reference to the last element)10std::cout << d1.empty();    // 0 (false)11
12std::sort(d1.begin(), d1.end());13
14auto it = std::find(d1.begin(), d1.end(), 3);15d1.insert(it, 10);          // 1, 2, 10, 3, 4, 516
17it = std::find(d1.begin(), d1.end(), 4);18d1.insert(it, d2.begin(), d2.end());19    // 1, 2, 10, 3, 10, 20, 30, 40, 50, 4, 520
21d1.swap(d2);                // Swaps the two deques
max_size(): Returns the maximum number of elements a vector can theoretically hold on the currentsystem. This is typically a very large number and depends on system and implementation limits.
91person p{"Kyungjae", 30};2std::deque<person> d;3
4d.push_back(p);                 // Add p to the back (copy is made)5d.pop_back();                   // Remove the last element (p in this case)6d.push_front(person{"Sunny", 20});7d.pop_front();                  // Remove element from the front8d.emplace_front("Yena", 5);     // Construct the object in-place. Very efficient!9d.emplace_back("Sunny", 20);    // Construct the object in-place. Very efficient!L4: Remember, all standard container classes store copies of the elements they hold. So in this case, a copy of
pis made.L6: Creates a temporary (unnamed) person object and adds it to the deque using move semantics.
L8: Constructs the person object directly in place using the constructor. Very efficient - no moves, no copies. It’s built exactly where it needs to be. Use this!
std::dequestd::deque is ideal when you need fast insertions or deletions at both the front and back of the container. It is not optimized for frequent insertions or removals in the middle. If your use case involves modifying elements in the middle, consider using std::list instead.
x
1
6// Template function to print elements of any deque.7template <typename T>8void print(const std::deque<T> &d)9{10    std::cout << "[ ";11    for (const auto &elem : d)12    {13        std::cout << elem << " ";14    }15    std::cout << "]" << std::endl;16}17
18// [], at()19void test1(void)20{21    std::cout << "\nTEST1" << std::endl;22
23    std::deque<int> d{1, 2, 3, 4, 5};24    print(d);25
26    d = {2, 4, 5, 6};27    print(d);28
29    std::deque<int> d1(10, 0);    // ten 0s in the deque30    print(d1);31
32    // We use deques for operations at the front and the back, but they also33    // allow random access to the elements in constant time.34    d1[0] = 100;35    d1.at(1) = 200;36    print(d1);37}38
39// push_front(), pop_front(), push_back(), pop_back(), front(), back(), size()40void test2(void)41{42    std::cout << "\nTEST2" << std::endl;43
44    std::deque<int> d{0, 0, 0};45    print(d);46
47    d.push_back(5);48    d.push_back(8);49    print(d);50
51    d.push_front(2);52    d.push_front(1);53    print(d);54
55    std::cout << "Front: " << d.front() << std::endl;56    std::cout << "Back: " << d.back() << std::endl;57    std::cout << "Size: " << d.size() << std::endl;58
59    d.pop_back();60    d.pop_front();61    print(d);62}63
64// push_front(), push_back()65void test3(void)66{67    std::cout << "\nTEST3" << std::endl;68
69    // Insert all even numbers into the back of a deque and all odd numbers into70    // the front.71    std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};72    std::deque<int> d;73
74    for (const auto &elem : v)75    {76        if (elem % 2 == 0)77        {78            d.push_back(elem);79        }80        else81        {82            d.push_front(elem);83        }84    }85
86    print(d);87}88
89// push_front(), push_back(), clear()90void test4(void)91{92    std::cout << "\nTEST4" << std::endl;93
94    // push_front() vs. push_back ordering.95    std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};96    std::deque<int> d;97
98    for (const auto &elem : v)99    {100        d.push_front(elem);101    }102    print(d);103    d.clear();104
105    for (const auto &elem : v)106    {107        d.push_back(elem);108    }109    print(d);110}111
112// std::copy(), std::front_inserter(), std::back_inserter()113void test5(void)114{115    std::cout << "\nTEST5" << std::endl;116
117    // Same as test4(), but using std::copy.118    std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};119    std::deque<int> d;120
121    122    // Same effect as the push_front().123    std::copy(v.begin(), v.end(), std::front_inserter(d));124    print(d);125
126    d.clear();127
128    // Same effect as the push_back().129    std::copy(v.begin(), v.end(), std::back_inserter(d));130    print(d);131}132
133int main(int argc, char *argv[])134{135    test1();136    test2();137    test3();138    test4();139    test5();140    return 0;141}261
2TEST13[ 1 2 3 4 5 ]4[ 2 4 5 6 ]5[ 0 0 0 0 0 0 0 0 0 0 ]6[ 100 200 0 0 0 0 0 0 0 0 ]7
8TEST29[ 0 0 0 ]10[ 0 0 0 5 8 ]11[ 1 2 0 0 0 5 8 ]12Front: 113Back: 814Size: 715[ 2 0 0 0 5 ]16
17TEST318[ 9 7 5 3 1 2 4 6 8 10 ]19
20TEST421[ 10 9 8 7 6 5 4 3 2 1 ]22[ 1 2 3 4 5 6 7 8 9 10 ]23
24TEST525[ 10 9 8 7 6 5 4 3 2 1 ]26[ 1 2 3 4 5 6 7 8 9 10 ]