Deques (Double-Ended Queues)

November 19, 2025
#deque #double-ended-queue #data-structures #algorithms

Introduction

A deque (pronounced “deck”) is short for “double-ended queue”—a linear data structure that allows insertion and deletion at both the front and the rear. Think of it as a hybrid between a stack and a queue, offering the flexibility to add or remove elements from either end.

This versatility makes deques powerful for problems requiring sliding windows, palindrome checking, and maintaining ordered sequences with efficient operations at both ends. By the end of this tutorial, you’ll understand when deques shine and how to implement them efficiently.

If you’re new to data structures, review Big-O Notation, Arrays, Linked Lists, Stacks, and Queues first.

What is a deque?

A deque is a generalized queue that supports four primary operations:

  1. addFront (or pushFront): Add an element to the front
  2. addRear (or pushRear): Add an element to the rear
  3. removeFront (or popFront): Remove and return the element from the front
  4. removeRear (or popRear): Remove and return the element from the rear

Additional operations include: 5. peekFront: View the front element without removing it 6. peekRear: View the rear element without removing it 7. isEmpty: Check if the deque is empty 8. size: Get the number of elements

The key feature: bidirectional access allows adding and removing from both ends efficiently.

Why use a deque?

Choose a deque when:

  1. You need efficient operations at both ends (unlike queues or stacks)
  2. You’re implementing sliding window algorithms
  3. You need a data structure that can act as both a stack and a queue
  4. You’re checking for palindromes or processing sequences bidirectionally
  5. You’re implementing work-stealing algorithms in concurrent systems
  6. You need to maintain a limited-size buffer with eviction from either end

Avoid a deque when:

  • You only need single-end access (use a stack or queue)
  • You need random access to elements (use an array)
  • You need priority-based ordering (use a priority queue)

Real-world applications

Deques are used in various scenarios:

  • Browser history: Navigate forward and backward through pages
  • Undo/Redo systems: Add to front for undo, remove from rear for old operations
  • Sliding window problems: Maintain maximum/minimum in a window
  • Work stealing: In multi-threaded schedulers, threads steal work from both ends
  • Palindrome checking: Compare characters from both ends moving inward
  • A pathfinding*: Efficiently manage the open set with bidirectional access
  • Text editors: Managing cursor position with efficient insertion/deletion

Deque vs Stack vs Queue

Feature Deque Stack Queue
Front insertion ✅ O(1) ✅ O(1) (top) ❌ Not typical
Rear insertion ✅ O(1) ❌ Not typical ✅ O(1)
Front removal ✅ O(1) ✅ O(1) (top) ✅ O(1)
Rear removal ✅ O(1) ❌ Not typical ❌ Not typical
Use as stack ✅ Yes ✅ Yes ❌ No
Use as queue ✅ Yes ❌ No ✅ Yes

Core operations and complexity

All primary deque operations are constant time:

  • addFront: O(1) — add element to front
  • addRear: O(1) — add element to rear
  • removeFront: O(1) — remove and return front element
  • removeRear: O(1) — remove and return rear element
  • peekFront: O(1) — view front element
  • peekRear: O(1) — view rear element
  • isEmpty: O(1) — check if empty
  • size: O(1) — get number of elements
  • Space: O(n) — where n is the number of elements

Deque implementation

Deques are best implemented using doubly linked lists for true O(1) operations at both ends. Some languages provide built-in deque implementations.

Doubly linked list-based deque

Using built-in deques

Many languages provide optimized deque implementations:

Common deque problems

1. Palindrome checker

Check if a string is a palindrome by comparing from both ends:

2. Sliding window maximum

Find the maximum value in each sliding window of size k:

3. Implement a circular tour (gas stations problem)

Use a deque to find the starting point for a circular tour:

Common pitfalls

  • Array-based front operations are O(n): Using array unshift() or shift() is inefficient. Use doubly linked lists or built-in deques.
  • Forgetting to update both pointers: When removing the last element, ensure both front and rear are set to null
  • Not checking for empty deque: Always verify before removing or peeking
  • Confusing which end is which: Clearly document front vs rear in your implementation
  • Memory management: In manual-memory languages, free nodes properly

When to prefer other data structures

  • Need single-end access only → Use stack or queue
  • Need random access → Use array
  • Need priority ordering → Use priority queue (heap)
  • Need key-based lookup → Use hash table

Practice problems

  1. Implement a deque using a circular array with fixed capacity
  2. Reverse a deque in place
  3. Find the first negative integer in every window of size k
  4. Implement LRU cache using a deque and hash map
  5. Design a browser history system with forward/back buttons using a deque
  6. Solve the “Maximum of all subarrays of size k” using a deque
  7. Check if a given array can be divided into pairs of consecutive numbers
  8. Implement a deque-based solution for the “Trapping Rain Water” problem
  9. Design an age-based priority system using a deque
  10. Solve the “Jump Game” problem using a deque for optimization

Complexity summary

  • Time complexity:
    • addFront: O(1)
    • addRear: O(1)
    • removeFront: O(1)
    • removeRear: O(1)
    • peekFront: O(1)
    • peekRear: O(1)
    • isEmpty: O(1)
    • size: O(1)
  • Space complexity: O(n) where n is the number of elements

Deques combine the best of stacks and queues, providing constant-time operations at both ends and making them ideal for bidirectional data processing.

Thanks for visiting
We are actively updating content to this site. Thanks for visiting! Please bookmark this page and visit again soon.
Sponsor