Deque in Python
A deque (short for double-ended queue) is a data structure that allows inserting and removing elements from both ends efficiently. Python provides a built-in collections.deque class that is optimized for fast appends and pops from both ends.
1. Why Use a Deque Instead of a List?
Python lists (list) support adding and removing elements from both ends, but operations on the left side (beginning) can be slow because lists are implemented as dynamic arrays.
Time Complexity Comparison
| Operation | list (Time Complexity) | deque (Time Complexity) |
|---|---|---|
Append to right (append()) | O(1)O(1)O(1) | O(1)O(1)O(1) |
Pop from right (pop()) | O(1)O(1)O(1) | O(1)O(1)O(1) |
Insert at left (insert(0, x)) | O(n)O(n)O(n) | O(1)O(1)O(1) |
Pop from left (pop(0)) | O(n)O(n)O(n) | O(1)O(1)O(1) |
- If you frequently need to add or remove elements from both ends, use
collections.dequeinstead of a list.
2. Creating a Deque
You must import deque from the collections module before using it.
from collections import deque
# Creating an empty deque
d = deque()
# Creating a deque with initial elements
d = deque([1, 2, 3, 4, 5])
print(d)
Output:
deque([1, 2, 3, 4, 5])
3. Basic Operations on Deque
3.1. Adding Elements
| Method | Description |
|---|---|
append(x) | Add x to the right (end) |
appendleft(x) | Add x to the left (beginning) |
extend(iterable) | Add multiple elements to the right |
extendleft(iterable) | Add multiple elements to the left (added in reverse order) |
Example
d = deque([2, 3, 4])
# Append to right
d.append(5)
print(d)
# Append to left
d.appendleft(1)
print(d)
# Extend right
d.extend([6, 7])
print(d)
# Extend left
d.extendleft([0, -1])
print(d)
Output:
deque([2, 3, 4, 5])
deque([1, 2, 3, 4, 5])
deque([1, 2, 3, 4, 5, 6, 7])
deque([-1, 0, 1, 2, 3, 4, 5, 6, 7])
Note: extendleft(iterable) adds elements in reverse order.
3.2. Removing Elements
| Method | Description |
|---|---|
pop() | Remove and return the rightmost element |
popleft() | Remove and return the leftmost element |
remove(x) | Remove first occurrence of x |
clear() | Remove all elements |
Example:
d = deque([10, 20, 30, 40, 50])
# Pop from right
d.pop()
print(d)
# Pop from left
d.popleft()
print(d)
# Remove specific element
d.remove(30)
print(d)
# Clear the deque
d.clear()
print(d)
Output:
deque([10, 20, 30, 40])
deque([20, 30, 40])
deque([20, 40])
deque([])
3.3. Accessing Elements
Deque supports indexing like lists.
d = deque([10, 20, 30, 40, 50])
print(d[0]) # First element
print(d[-1]) # Last element
Output:
10
50
However, slicing (e.g., d[1:3]) is not supported. You must convert it to a list first: list(d)[1:3].
4. Rotating the Deque
| Method | Description |
|---|---|
rotate(n) | Rotate n places to the right. If n is negative, rotate left. |
Example
d = deque([1, 2, 3, 4, 5])
# Rotate right by 2 positions
d.rotate(2)
print(d)
# Rotate left by 1 position
d.rotate(-1)
print(d)
Output:
deque([4, 5, 1, 2, 3])
deque([5, 1, 2, 3, 4])
5. Maximum Length (Bounded Deques)
A deque can have a maximum size (maxlen). When it exceeds this limit, the oldest element is automatically removed.
Example
d = deque(maxlen=3)
d.append(1)
d.append(2)
d.append(3)
print(d)
d.append(4) # Oldest element (1) is removed
print(d)
Output:
deque([1, 2, 3], maxlen=3)
deque([2, 3, 4], maxlen=3)
Useful for implementing caches, logs, or sliding windows.
6. Deque as a Stack (LIFO)
| Stack Operation | Deque Method |
|---|---|
| Push (add to top) | append(x) |
| Pop (remove from top) | pop() |
Example
stack = deque()
# Push elements
stack.append(10)
stack.append(20)
stack.append(30)
print(stack)
# Pop elements (LIFO)
print(stack.pop())
print(stack.pop())
Output:
deque([10, 20, 30])
30
20
7. Deque as a Queue (FIFO)
| Queue Operation | Deque Method |
|---|---|
| Enqueue (add to rear) | append(x) |
| Dequeue (remove from front) | popleft() |
Example
queue = deque()
# Enqueue elements
queue.append(10)
queue.append(20)
queue.append(30)
print(queue)
# Dequeue elements (FIFO)
print(queue.popleft())
print(queue.popleft())
Output:
deque([10, 20, 30])
10
20
8. Thread-Safe Deques
deque is thread-safe for append/pop operations from both ends without needing locks. However, for complex operations, threading.Lock is recommended.
Conclusion
dequeis faster than lists for appending/removing at both ends.- It can function as stack, queue, or circular buffer.
- Supports rotations, bounded size, and efficient memory usage.