C++ Deque

Welcome to The Coding College! In this tutorial, we’ll dive into deque (double-ended queue) in C++, a versatile data structure provided by the Standard Template Library (STL).

What Is a Deque?

A deque (double-ended queue) is a linear data structure that allows insertion and deletion of elements from both the front and back. Unlike stacks and queues, which are restricted to LIFO and FIFO operations, a deque offers greater flexibility.

Key Characteristics:

  • Dynamic Size: The size of a deque can grow or shrink dynamically.
  • Access From Both Ends: You can add or remove elements from both ends.

Declaring a Deque

To use deques in C++, include the <deque> header.

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

int main() {
    deque<int> myDeque; // Declare a deque of integers

    return 0;
}

Common Operations

1. Push Elements

You can add elements to both the front and back of the deque using push_front and push_back.

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

int main() {
    deque<int> myDeque;

    myDeque.push_back(10);   // Add 10 to the back
    myDeque.push_back(20);   // Add 20 to the back
    myDeque.push_front(5);   // Add 5 to the front

    cout << "Front: " << myDeque.front() << endl; // Access the front element
    cout << "Back: " << myDeque.back() << endl;   // Access the back element

    return 0;
}

Output:

Front: 5  
Back: 20  

2. Pop Elements

Remove elements from either the front or the back using pop_front and pop_back.

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

int main() {
    deque<int> myDeque;

    myDeque.push_back(10);
    myDeque.push_back(20);
    myDeque.push_front(5);

    myDeque.pop_front(); // Remove the front element (5)

    cout << "Front after pop: " << myDeque.front() << endl;

    myDeque.pop_back(); // Remove the back element (20)

    cout << "Back after pop: " << myDeque.back() << endl;

    return 0;
}

Output:

Front after pop: 10  
Back after pop: 10  

3. Access Elements by Index

Deques allow direct access to elements using the [] operator or at().

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

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

    cout << "Element at index 1: " << myDeque[1] << endl;    // Using []
    cout << "Element at index 2: " << myDeque.at(2) << endl; // Using at()

    return 0;
}

Output:

Element at index 1: 20  
Element at index 2: 30  

4. Check Size and Empty Status

Use size() to get the number of elements and empty() to check if the deque is empty.

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

int main() {
    deque<int> myDeque;

    cout << "Deque is empty: " << boolalpha << myDeque.empty() << endl;

    myDeque.push_back(10);

    cout << "Deque size: " << myDeque.size() << endl;

    return 0;
}

Output:

Deque is empty: true  
Deque size: 1  

5. Insert and Erase Elements

You can insert or remove elements at specific positions using insert and erase.

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

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

    myDeque.insert(myDeque.begin() + 1, 15); // Insert 15 at index 1

    for (int x : myDeque) {
        cout << x << " ";
    }
    cout << endl;

    myDeque.erase(myDeque.begin() + 2); // Remove element at index 2

    for (int x : myDeque) {
        cout << x << " ";
    }

    return 0;
}

Output:

10 15 20 30  
10 15 30  

Iterating Over a Deque

You can use iterators to traverse a deque.

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

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

    for (auto it = myDeque.begin(); it != myDeque.end(); ++it) {
        cout << *it << " ";
    }

    return 0;
}

Output:

10 20 30 40  

Applications of Deques

  1. Sliding Window Problems: Efficiently handle a fixed-size window over a dataset.
  2. Palindrome Checking: Verify whether a string is a palindrome.
  3. Double-Ended Buffers: Process data from both ends.
  4. Scheduling Algorithms: Manage tasks that require both FIFO and LIFO operations.

Real-World Example: Sliding Window Maximum

Find the maximum value in a sliding window of size k in an array.

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

void slidingWindowMax(vector<int> arr, int k) {
    deque<int> dq;

    for (int i = 0; i < arr.size(); ++i) {
        // Remove elements outside the current window
        if (!dq.empty() && dq.front() == i - k) {
            dq.pop_front();
        }

        // Remove elements smaller than the current element
        while (!dq.empty() && arr[dq.back()] < arr[i]) {
            dq.pop_back();
        }

        dq.push_back(i);

        // Output maximum for the current window
        if (i >= k - 1) {
            cout << arr[dq.front()] << " ";
        }
    }
}

int main() {
    vector<int> arr = {1, 3, 1, 2, 5, 3, 6, 7};
    int k = 3;

    slidingWindowMax(arr, k);

    return 0;
}

Output:

3 3 5 5 6 7  

Summary

  • Advantages: Dynamic size, access to both ends.
  • Key Methods: push_back, push_front, pop_back, pop_front, front, back, insert, erase.
  • Applications: Efficient in problems requiring operations at both ends of a sequence.

Learn More at The Coding College

For more tutorials on C++ and advanced data structures, visit The Coding College.

Leave a Comment