Deque in C++

Learn via video course
FREE
View all courses
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
C++ Course: Learn the Essentials
C++ Course: Learn the Essentials
by Prateek Narang
1000
5
Start Learning
Topics Covered

Overview

Deque stands for double-ended queues. Double-ended queues are a type of queue that allows for insertion and deletion at both ends. These dynamically sized sequence containers can be enlarged or contracted on both ends (either from its back or front). The header file to be included is deque.

Sequence containers with the ability to expand and contract on both ends are known as double-ended queues.

Real Life Example of Deque

You might have been using undo and redo operations in lots of software i.e, Microsoft Word, Libre Office, Notepad, Visual Code, etc. Let's think about a high-level approach of how it might have been implemented. The first thing that might be clear to you is that there is a need of storing some data related to undo/redo operations in the data structure. Although there could be several data structures which we can use to store deque proves it worthiness because of some reasons, let's discuss one by one.

What if We Use Vector or Array?

  • First of all we need to have two separate arrays to store the undo operations and redo operations.
  • Now if our operations keep increasing then the expansion of the array might be costly because as we know entire array is copied into newly allocated memory.
  • If we did redo then the corresponding operation should be removed from the undo operations array, or vice-versa. As we know entire array is shifted when we remove any element from the array it would be highly time consuming.
  • Keeping these points as inference we can say that array is not good for these cases.

What if We Use Stack?

  • We need to maintain two stacks, one for redo operation and the other for undo operations.
  • Each time when a undo happens, we need to pop the operation from the top undo of the stack and push it to the top of the redo stack.

What if We Use Queue?

  • We need to maintain two queues one for undo operations and the other for redo operations.
  • Each time a undo happens, we need to pop the operation from the undo queue and push it to the redo queue and vice-versa.

Deque Over All of These

  • Although Stack and queues are solving our problem efficiently as compared to the array, still there is an issue of maintaining two data variables.
  • By using deque, we need to just maintain one variable.
  • For each undo we can insert the operation from the front end and for redo we can delete the first element from the front end and add it to the back end of the deque.
  • One end will represent the undo operations and other end will represent the redo operations.
  • This entire flow of undo and redo will proceed in a circular manner.
  • Also, here we can fix the maximum size of deque to set the limit of undo and redo operations.
  • We can therefore conclude that deque is the best option for dealing with these kind of problems.

Why Deque was Implemented?

The abstract data type is created from concrete data types in order to create a unique data structure that can have its own properties, advantages, and disadvantages. These attributes are used in order to analyze the situation of the problem statement, like whether the current data structure is best suited to store and manipulate data for a given problem statement. In order to overcome the limitations of one-ended insertion and deletion of stacks and queues, Deque was introduced. By dynamically shrinking and growing at runtime, it allows inserting and deleting from both ends. Informally, we can say that deque has powers of queue and stack both.

Comparison with Vectors

They're comparable to vectors, but they're more efficient in element insertion and deletion because of insertion and deletion at both ends within constant time. Although vectors and deques have a similar interface and can be used for similar tasks, they operate in quite different ways internally. The elements of a deque can be spread across various locations on memory. The container maintains the required info internally to deliver direct access to any of its elements in constant time and with a uniform sequential interface. In contrast, vectors use a single array to store, and this array keeps expanding.

Note:- Double ended queue can be implemented easily by using the doubly linked list.

Basic Syntax

The basic syntax of deque data structure is as follows:

data_type: Data Type of the List dq_name: Variable Name for the Deque

Deque Operation and Illustration

Deque allows some of the major unique operations like insertion and deletion from both ends also we can see the front and rear data elements within the constant time complexity. The implementation of the deque is programmer dependent, we can use any concrete data structure to build our abstract data structure deque, but for this section, we are not going to build the entire class for the same, because C++ has inbuilt implementation of deque in STL.

Push Front

This operation adds the element to the deque from the front end.

Output:

Explanation:

Push Front

Pop Front

This operation removes the first element from the front end.

Output:

Explanation: Pop Front

Push Rear

Similar to the last ones, this operation adds the element from the rear/back end.

Note:- In STL, rear is termed as back.

Output:

Explanation: Push Rear

Pop Rear

This operation removes the first element from the rear end.

Output:

Explanation: Pop Rear

Get Front

This operation fetches the first element from front side.

Output:

Explanation: Get Front

Get Rear

This operation provides the first element from rear side.

Output:

Explanation: Get Rear

Deque STL Functions

Standard Template Library contains implementation of Deque, as we are dicussing from the Programming point of view, below are the various deque STL functions with descriptions:

FunctionDescription
insert()It inserts a new element right before the specified place and returns an iterator pointing to the first of the newly added elements.
front()It is used to refer to the deque container's first element.
back()It is used to refer to the deque container's last element.
push_front()It is used to insert elements from the front of a deque.
push_back()It is used to insert elements from the back of a deque.
pop_front()It is used to delete elements from the front of a deque.
pop_back()It is used to delete elements from the back of a deque.
clear()It is used to clear the deque container of all its contents. It will reduce the deque's size to 0.
erase()It is used to delete elements from a container based on their position or range.
emplace_front()It is used to  append a new element to the deque's front.
emplace_back()It's used to  append a new element to the deque's end.
begin()It is used to return an iterator referring to the deque container's first element.
end()It is used to return an iterator referring to the deque container's last element.
rbegin()It is used to return a reverse iterator which points to the last element of the deque (i.e., its reverse beginning).
rend()It's used to return a reverse iterator that points to the deque's last element (i.e., its reverse beginning).
cbegin()It is used to return a constant iterator referring to the container's first element; the iterator cannot be used to modify the deque, only to traverse it.
empty()It is used to determine whether or not the deque container is empty. It's a boolean value.
size()It's used to get the deque container's size.
max_size()It is used to get the count of how many items a deque container can carry at once.
assign()It is used to assign values to the deque container.
resize()It is used to modify the size of the deque container.
find()It is used to find the element within a particular numeric range. It r eturns an iterator to the first element that matches to val in the range [first, last]. The function will return last if no such element is found.

Examples

Explanation of all Important Deque Functions

There are various Deque STL functions available in C++. Let’s look at the following example to understand all general purpose Deque Functions.

Output:

Explanation:

  • Deque variable is declared using: deque<int> dq;.
  • dq.push_front(1); inserts an 1 at the starting of the dq. Now, the deque dq is : { 1 }.
  • dq.push_back(2); inserts an 2 at the ending of the dq. Now, the deque dq is : {1, 2}.
  • dq.push_front(3); inserts an 3 at the starting of the dq. Now, the deque dq is : {3, 1, 2}.
  • dq.push_back(4); inserts an 4 at the ending of the dq. Now, the deque dq is : {3, 1, 2, 4}.
  • dq.push_back5); inserts an 5 at the endingg of the dq. Now, the deque dq is : {3, 1, 2, 4, 5}.
  • dq.max_size(); returns the maximum size of the dq.
  • dq.size(); returns the number of elements dq has, that is 5.
  • dq.front(); returns the value of the first element of the deque. In the dq {3, 1, 2, 4, 5}, 3 is the first element, so it will return 3.
  • dq.back(); returns the value of the last element of the deque. In the dq {3, 1, 2, 4, 5}, 5 is the last element, so it will return 5.
  • dq.at(3); returns the value of the element at the third index of the deque. In the dq {3, 1, 2, 4, 5}, 4 is at third index, so it will return 4.
  • dq.pop_back(); removes an element from the ending of the dq. In the dq {3, 1, 2, 4, 5}, 5 is the last element, so it will remove 5. Now, the deque dq is : {3, 1, 2, 4}.
  • dq.pop_front(); removes an element from the starting of the dq. In the dq {3, 1, 2, 4, 5}, 3 is the last element, so it will remove 5. Now, the deque dq is : { 1, 2, 4}.

Sliding Window Technique

If we want to find all subarrays(called windows) continuously, then the sliding window technique reduces the nested loop to find all required portions of an array.

The deque can be used to store the windows at each forwarded step, we can just pop the item from the front and push a new item at the rear.

Digression: This has a real life application in computer networking, where sender sends multiple frames to reciever in a sliding window format. The protocol is named Sliding window Protocol in Networking.

Output:

Explanation:

  • Here you can see we have created an initial window, and later we are just removing from the front of the deque and adding a new item to the rear.
  • This process slides the window at each step.

Applications

The following are some applications of deque:

  • Deque can be used to implement stacks and queues. Thus it has many applications.
  • Task scheduling for various processors in a multiprocessor system is implemented using a scheduling algorithm. This implementation employs a deque, with the processor executing the first element from the deque.
  • Many activities are available in software applications. "Undo" is one of them. When we do an undo action multiple times, the results are saved in a list. This list is kept as a deque to easily add or remove entries from any end.
  • Another application of deque is in the implementation of browsers to save history. URLs that have been recently visited are added to the front of the deque, and the URL in the rear is removed after a certain amount of insertions to the front.

Conclusion

  • Deque stands for double-ended queues. These dynamically sized sequence containers can be enlarged or contracted on both ends.
  • The header file to be included for using deque operations is deque.
  • Deque is more efficient than vector due to insertion/deletion at both ends.
  • Deque has various member functions such as push_front(), push_back(), pop_front(), pop_back(), etc.
  • Deque has real-life applications such as undo operations, web browsers to save history, etc.

Read More: