Hello! Welcome to your next lesson on data structures.
In our previous session, you learned how to ingeniously implement a queue's FIFO behavior using two LIFO stacks, and importantly, you analyzed its O(1) amortized time complexity. This was a great exercise in thinking about how to build one data structure from another.
Today, we move on to a more versatile structure: the Deque (pronounced "deck"), which stands for Double-Ended Queue. As the name implies, it combines the features of both a stack and a queue. The goal for this lesson is to implement a deque using a doubly linked list. This is the most natural and efficient way to build a deque, and understanding this implementation is fundamental for many advanced problems.
1. What is a Deque?
A deque is a linear collection of elements that allows insertion and deletion at both ends—the front and the rear. This flexibility makes it a powerful tool.
The primary operations are:
insertFront(): Adds an item to the front of the deque.insertRear(): Adds an item to the back of the deque.deleteFront(): Removes an item from the front of the deque.deleteRear(): Removes an item from the back of the deque.
Why is a doubly linked list the perfect choice for this? Because each node in a doubly linked list holds pointers to both the next and the previous node. By maintaining pointers to the first (front) and last (rear) nodes of the list, we can access both ends directly and perform all four operations in constant time, O(1).

2. Building the Deque: The Node and Class Structure
First, let's define the building blocks. We need a Node class that can store data and link to its neighbors in both directions. We also need a Deque class that will hold references to the front and rear nodes.
Implementation of Deque using doubly linked list
The article 'Implementation of Deque using doubly linked list' from GeeksforGeeks provides a clear and concise starting point. Let's look at the basic Java code for the Node and the initial MyDeque class.
Focus on the Java code snippet provided in the section 'Doubly Linked List Representation of Deque'. Note how the Node class has data, prev, and next fields, and the myDeque class initializes front and rear to null.
Here's the essential structure in Java:
// The node of a doubly linked list
class Node {
int data;
Node prev;
Node next;
// Constructor to create a new node
Node(int data) {
this.data = data;
this.prev = null;
this.next = null;
}
}
// A Deque class implemented using a doubly linked list
class MyDeque {
private Node front;
private Node rear;
private int size; // Good practice to keep track of size
public MyDeque() {
front = null;
rear = null;
size = 0;
}
}
Now, let's implement the core operations one by one.
3. Implementing the Deque Operations
We will now walk through the logic for each of the four main operations. The key is to correctly manage the front, rear, next, and prev pointers for each case.
a) Insertion at the Front (insertFront)
- Create a
newNodewith the given data. - If the deque is empty (
front == null), bothfrontandrearshould point to thenewNode. - If the deque is not empty, we need to wire the
newNodein at the beginning:newNode.nextpoints to the oldfront.- The old
front.prevpoints back to thenewNode. - Finally, update
frontto be thenewNode.
Implementation of Deque using doubly linked list
Let's study the code for insertFront. Pay close attention to the two cases: inserting into an empty list versus a non-empty one.
Read the section titled 'Insertion at Front' and examine the Java code snippet.
b) Insertion at the Rear (insertRear)
This is the mirror image of insertFront.
- Create a
newNode. - If the deque is empty, both
frontandrearpoint to thenewNode. - If the deque is not empty:
newNode.prevpoints to the oldrear.- The old
rear.nextpoints forward to thenewNode. - Update
rearto be thenewNode.
Implementation of Deque using doubly linked list
Now, let's look at the insertRear implementation. The logic is symmetric to insertFront.
Read the section 'Insertion at Rear' and examine its Java code snippet.
Test your understanding!
Starting with an empty deque, what do the front and rear pointers refer to after this sequence of operations? What are the prev and next pointers of the node containing 20?
insertFront(10)insertRear(20)insertFront(5)
Show answer
insertFront(10): The deque is[10].frontandrearboth point to the node with value 10.insertRear(20): The deque is[10, 20].frontpoints to node 10,rearpoints to node 20. Node 10'snextis node 20, and node 20'sprevis node 10.insertFront(5): The deque is[5, 10, 20].frontpoints to node 5,rearpoints to node 20.
The node containing 20 is the rear.
- Its
prevpointer points to the node containing10. - Its
nextpointer isnull.
c) Deletion from the Front (deleteFront)
- Check for underflow: If the deque is empty (
front == null), there's nothing to delete. - If there is only one element (
front == rear), set bothfrontandreartonull. - If there are multiple elements:
- Move
frontto the next node:front = front.next. - The new
front'sprevpointer must be set tonullto sever the link to the old front node.
- Move
d) Deletion from the Rear (deleteRear)
Symmetrically, for deletion from the rear:
- Check for underflow.
- If there is only one element, set both
frontandreartonull. - If there are multiple elements:
- Move
rearto the previous node:rear = rear.prev. - The new
rear'snextpointer must be set tonull.
- Move
Implementation of Deque using doubly linked list
Let's review the code for the deletion operations. Again, notice the handling of edge cases like an empty or single-element deque.
Read the sections 'Deletion from Front end' and 'Deletion from Rear end'. Study the Java code snippets for both deleteFront and deleteRear.
4. Code Consolidation and a Pro Tip for Interviews
Putting it all together, we get a complete MyDeque class. The resource from GeeksforGeeks provides a full implementation including helper methods, which is a great reference.
Implementation of Deque using doubly linked list
This section of the article provides the complete, runnable Java code for the deque, including a main method to test it.
Briefly scan through the full implementation in the 'Below is the implementation of the above approach:' section. This will help you see how all the pieces fit together into a single class.
Pro Tip: Simplifying Edge Cases with a Dummy Node
You might have noticed that our insertion and deletion logic requires if/else statements to handle empty lists or single-element lists. In an interview, demonstrating a way to write cleaner, more robust code is a huge plus. This is where the dummy node (or sentinel node) technique, which you specifically asked about, comes in.
A dummy node is a placeholder node that is never removed from the list. It doesn't hold any meaningful data. We can structure our list as a circular doubly linked list where the dummy node's next pointer points to the front of the deque, and its prev pointer points to the rear. The front's prev and the rear's next both point back to the dummy node.
Why is this better?
- No more nulls: Every "real" node always has a non-null
prevandnext(they point to another real node or the dummy node). - No more edge cases: An "empty" list is one where the dummy node just points to itself. The logic for insertion and deletion becomes the same whether the list is empty, has one element, or has many elements. This eliminates almost all
if (front == null)checks.
The OpenDataStructures textbook provides an excellent explanation of why a dummy node is so useful in a doubly linked list.
Read the section '3.2 DLList: A Doubly-Linked List' to understand the motivation for the dummy node. Then, review the section '3.2.1 Adding and Removing' to see how the addBefore and remove methods are implemented without special case handling, thanks to the dummy node.
With a dummy node, insertFront becomes a call to addBefore(dummy.next, data) and insertRear becomes addBefore(dummy, data). This is a very elegant solution that showcases a deep understanding of linked list manipulations.
Conclusion
Great job! You have now learned how to implement a deque from first principles using a doubly linked list. This is a foundational skill that reinforces your understanding of pointers and data structure design.
Key Takeaways:
- A Deque allows O(1) insertion and deletion at both the front and rear.
- A doubly linked list is the natural data structure to implement a deque, using
frontandrearpointers for direct access. - Careful pointer manipulation is required for the
insertanddeleteoperations, especially handling theprevandnextlinks. - The dummy node technique is a powerful way to simplify code and eliminate edge-case handling for linked list operations, a valuable pattern to know for technical interviews.
Preview of the next lesson:
Now that you have built a deque and understand its O(1) efficiency, it's time to put it to use. In the next lesson, we will tackle a classic and challenging interview problem: "Sliding Window Maximum". You will see how the unique properties of the deque make it the perfect tool to solve this problem efficiently.