Home C++ C++ Standard Template Library (STL) deque tutorial

C++ Standard Template Library (STL) deque tutorial

The deque (double-ended queue) in the C++ Standard Template Library (STL) is a sequence container that supports fast insertion and deletion at both the front and back.

It’s similar to vector but provides efficient operations on both ends, making it versatile for various applications.

Key Features of deque

  1. Double-ended: Supports insertion and deletion from both front and back.
  2. Dynamic resizing: Expands and contracts as needed, unlike static arrays.
  3. Random access: Elements can be accessed in constant time with an index, like vector.

Basic Syntax

#include <deque>
using namespace std;

deque<int> dq;

1. Basic Operations: Insertion and Deletion

The push_back and push_front functions add elements at the back and front, respectively, while pop_back and pop_front remove elements from the back and front.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque<int> dq;

    // Inserting elements at the back
    dq.push_back(10);
    dq.push_back(20);

    // Inserting elements at the front
    dq.push_front(5);

    cout << "Deque after insertions: ";
    for (int x : dq) {
        cout << x << " ";
    }
    cout << endl;

    // Removing elements from front and back
    dq.pop_front();
    dq.pop_back();

    cout << "Deque after pop_front and pop_back: ";
    for (int x : dq) {
        cout << x << " ";
    }
    cout << endl;

    return 0;
}

Output:

Deque after insertions: 5 10 20 
Deque after pop_front and pop_back: 10 

2. Accessing Elements

deque allows random access to elements using both the at function and [] operator. front and back functions access the first and last elements, respectively.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque<int> dq = {10, 20, 30, 40};

    cout << "Element at index 2: " << dq.at(2) << endl;
    cout << "First element: " << dq.front() << endl;
    cout << "Last element: " << dq.back() << endl;

    // Accessing elements using []
    cout << "Elements: ";
    for (size_t i = 0; i < dq.size(); i++) {
        cout << dq[i] << " ";
    }
    cout << endl;

    return 0;
}

Output:

Element at index 2: 30
First element: 10
Last element: 40
Elements: 10 20 30 40 

3. Initializing a deque with Values

You can initialize a deque with default values using the constructor that takes a size and a value.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    // Create a deque of size 5, initialized with the value 100
    deque<int> dq(5, 100);

    cout << "Deque initialized with default values: ";
    for (int x : dq) {
        cout << x << " ";
    }
    cout << endl;

    return 0;
}

Output:

Deque initialized with default values: 100 100 100 100 100 

4. Inserting Elements at Specific Positions

The insert function allows insertion at specific positions within the deque.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque<int> dq = {10, 20, 30};

    // Inserting 25 at the second position
    dq.insert(dq.begin() + 1, 25);

    cout << "Deque after inserting 25 at position 1: ";
    for (int x : dq) {
        cout << x << " ";
    }
    cout << endl;

    return 0;
}

Output:

Deque after inserting 25 at position 1: 10 25 20 30 

5. Removing Specific Elements

Elements can be removed from specific positions using the erase function, which takes an iterator.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque<int> dq = {10, 20, 30, 40};

    // Removing element at index 1
    dq.erase(dq.begin() + 1);

    cout << "Deque after erasing element at position 1: ";
    for (int x : dq) {
        cout << x << " ";
    }
    cout << endl;

    return 0;
}

Output:

Deque after erasing element at position 1: 10 30 40 

6. Clearing All Elements

The clear function removes all elements from the deque, making it empty.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque<int> dq = {10, 20, 30};

    cout << "Size before clear: " << dq.size() << endl;
    dq.clear();
    cout << "Size after clear: " << dq.size() << endl;

    return 0;
}

Output:

Size before clear: 3
Size after clear: 0

7. Checking if deque is Empty

The empty function returns true if the deque is empty, otherwise false.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque<int> dq;

    if (dq.empty()) {
        cout << "Deque is empty." << endl;
    }

    dq.push_back(10);

    if (!dq.empty()) {
        cout << "Deque is not empty." << endl;
    }

    return 0;
}

Output:

Deque is empty.
Deque is not empty.

8. Resizing a deque

The resize function changes the number of elements in the deque. If the new size is greater, new elements are added with a specified value; if smaller, extra elements are removed.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque<int> dq = {10, 20, 30};

    // Resizing to a larger size, filling with 100
    dq.resize(5, 100);

    cout << "Deque after resizing to 5 with default value 100: ";
    for (int x : dq) {
        cout << x << " ";
    }
    cout << endl;

    // Resizing to a smaller size
    dq.resize(2);
    cout << "Deque after resizing to 2: ";
    for (int x : dq) {
        cout << x << " ";
    }
    cout << endl;

    return 0;
}

Output:

Deque after resizing to 5 with default value 100: 10 20 30 100 100 
Deque after resizing to 2: 10 20 

9. Swapping Two deque Containers

The swap function exchanges the contents of two deque containers.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque<int> dq1 = {1, 2, 3};
    deque<int> dq2 = {4, 5, 6, 7};

    dq1.swap(dq2);

    cout << "Deque 1 after swap: ";
    for (int x : dq1) {
        cout << x << " ";
    }
    cout << endl;

    cout << "Deque 2 after swap: ";
    for (int x : dq2) {
        cout << x << " ";
    }
    cout << endl;

    return 0;
}

Output:

Deque 1 after swap: 4 5 6 7 
Deque 2 after swap: 1 2 3 

10. Using Iterators with deque

deque supports iterators, which allow for easy traversal and manipulation of elements.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque<int> dq = {10, 20, 30, 40, 50};

    cout << "Elements using iterator: ";
    for (auto it = dq.begin(); it != dq.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;

    // Using reverse iterator
    cout << "Elements in reverse order: ";
    for (auto rit = dq.rbegin(); rit != dq.rend(); ++rit) {
        cout << *rit << " ";
    }
    cout << endl;

    return 0;
}

Output:

Elements using iterator: 10 20 30 40 50 
Elements in reverse order: 50 40 30 20 10 

Summary Table of deque Operations

Operation Code Example Description
Insert at back dq.push_back(10); Adds element to the end
Insert at front dq.push_front(10); Adds element to the front
Remove from back dq.pop_back(); Removes element from the end
Remove from front dq.pop_front(); Removes element from the front
Access by index dq[i] or dq.at(i); Access element at specific index
First element dq.front(); Accesses the first element
Last element dq.back(); Accesses the last element
Insert at position dq.insert(dq.begin() + 1, 25); Inserts element at specified position
Remove at position dq.erase(dq.begin() + 1); Removes element at specified position
Clear all elements dq.clear(); Removes all elements
Check if empty dq.empty(); Returns true if deque is empty
Resize dq.resize(5, 100); Resizes deque, filling new slots as needed
Swap dq1.swap(dq2); Swaps contents of two deques
Iterate for (auto it = dq.begin(); it != dq.end(); ++it) Iterates through the deque

Complete Example

This example demonstrates initializing a deque, inserting and removing elements, resizing, and using iterators for traversal.

#include <iostream>
#include <deque>
using namespace std;

int main() {
    deque<int> dq = {10, 20, 30};

    // Insert elements at both ends
    dq.push_front(5);
    dq.push_back(40);

    // Display elements
    cout << "Deque after push_front and push_back: ";
    for (int x : dq) {
        cout << x << " ";
    }
    cout << endl;

    // Remove elements from both ends
    dq.pop_front();
    dq.pop_back();

    cout << "Deque after pop_front and pop_back: ";
    for (int x : dq) {
        cout << x << " ";
    }
    cout << endl;

    // Resize deque
    dq.resize(5, 100);

    cout << "Deque after resizing: ";
    for (int x : dq) {
        cout << x << " ";
    }
    cout << endl;

    // Using iterator to traverse
    cout << "Using iterator: ";
    for (auto it = dq.begin(); it != dq.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}

Sample Output:

Deque after push_front and push_back: 5 10 20 30 40 
Deque after pop_front and pop_back: 10 20 30 
Deque after resizing: 10 20 30 100 100 
Using iterator: 10 20 30 100 100 

Key Takeaways

  • deque in C++ provides a dynamic, double-ended queue, allowing efficient insertions and deletions at both ends.
  • It supports random access, similar to vector, and is well-suited for scenarios requiring manipulation at both ends.

You may also like