Deque
A deque is a double-ended queue implementation in Python’s collections module. It provides a versatile data structure that generalizes a stack and a queue by allowing efficient append and pop operations from both ends of the sequence. Unlike regular lists which have O(n) time complexity for inserting or removing elements at the beginning, deques provide O(1) time complexity for these operations on both ends.
Deques are particularly useful in scenarios requiring fast access to both ends of a sequence, such as implementing queues, stacks, sliding window algorithms, and tracking recent history with a limited size buffer. They are thread-safe for append and pop operations from different threads, making them valuable for concurrent programming applications.
Syntax
from collections import deque
d = deque([iterable[, maxlen]])
Parameters:
iterable
(Optional): A parameter providing initial data for the deque. If not provided, an empty deque is created.maxlen
(Optional): An integer specifying the maximum number of items allowed in the deque. When this limit is reached, adding new items causes items from the opposite end to be removed.
Return value:
A deque object returns a new deque object containing elements from the iterable in the same order (if provided), with an optional maximum length constraint.
Example 1: Creating and Using a Basic Deque
This example demonstrates basic deque operations including append()
, appendleft()
, pop()
, popleft()
, and index access:
from collections import deque# Create a dequenumbers = deque([1, 2, 3, 4, 5])print(f"Initial deque: {numbers}")# Add elements to both endsnumbers.append(6) # Add to the right endnumbers.appendleft(0) # Add to the left endprint(f"After adding elements: {numbers}")# Access elementsprint(f"First element: {numbers[0]}")print(f"Last element: {numbers[-1]}")# Remove elements from both endsright_element = numbers.pop() # Remove from the right endleft_element = numbers.popleft() # Remove from the left endprint(f"Popped from right: {right_element}")print(f"Popped from left: {left_element}")print(f"Final deque: {numbers}")
This example results in the following output:
Initial deque: deque([1, 2, 3, 4, 5])After adding elements: deque([0, 1, 2, 3, 4, 5, 6])First element: 0Last element: 6Popped from right: 6Popped from left: 0Final deque: deque([1, 2, 3, 4, 5])
Example 2: How to Append and Pop Items from Both Ends of a Deque
This example compares the performance of deque operations with list operations to demonstrate why deques are more efficient for certain tasks:
from collections import dequeimport timedef measure_performance(operation, times=10000):"""Measure the execution time of an operation."""start_time = time.perf_counter()operation(times)end_time = time.perf_counter()return end_time - start_timedef list_append_left(n):"""Add elements to the beginning of a list."""lst = []for i in range(n):lst.insert(0, i) # Insert at the beginning (expensive for lists)return lstdef deque_append_left(n):"""Add elements to the beginning of a deque."""d = deque()for i in range(n):d.appendleft(i) # Append to the left (efficient for deques)return d# Compare performance for left-side operationslist_time = measure_performance(list_append_left)deque_time = measure_performance(deque_append_left)print(f"Time to insert 10,000 items at the beginning:")print(f"List insert(0, item): {list_time:.6f} seconds")print(f"Deque appendleft(): {deque_time:.6f} seconds")print(f"Deque is approximately {list_time/deque_time:.1f}x faster")# Demonstrate bidirectional functionalityd = deque([1, 2, 3])print("\nBidirectional operations demonstration:")print(f"Initial deque: {d}")# Append operationsd.append(4) # Add to rightd.appendleft(0) # Add to leftprint(f"After appends: {d}")# Pop operationsright = d.pop() # Remove from rightleft = d.popleft() # Remove from leftprint(f"Popped from right: {right}")print(f"Popped from left: {left}")print(f"Final deque: {d}")
This example results in the following output (timing results may vary):
Time to insert 10,000 items at the beginning:List insert(0, item): 0.020001 secondsDeque appendleft(): 0.000671 secondsDeque is approximately 29.8x fasterBidirectional operations demonstration:Initial deque: deque([1, 2, 3])After appends: deque([0, 1, 2, 3, 4])Popped from right: 4Popped from left: 0Final deque: deque([1, 2, 3])
Codebyte Example: How to Use Deque to Build Efficient Queues and Stacks
This example demonstrates how to implement both a queue and a stack using a deque:
from collections import deque# Implementing a queue (FIFO) with dequequeue = deque()print("Queue Operations (FIFO):")# Enqueue operationsqueue.append('apple')queue.append('banana')queue.append('cherry')print(f"Queue after enqueuing: {queue}")# Dequeue operationsfirst_item = queue.popleft() # FIFO: first in, first outprint(f"Dequeued first item: {first_item}")print(f"Queue after dequeuing: {queue}")# Implementing a stack (LIFO) with dequestack = deque()print("\nStack Operations (LIFO):")# Push operationsstack.append(1)stack.append(2)stack.append(3)print(f"Stack after pushing items: {stack}")# Pop operationslast_item = stack.pop() # LIFO: last in, first outprint(f"Popped last item: {last_item}")print(f"Stack after popping: {stack}")# Bounded history example with maxlenhistory = deque(maxlen=3)actions = ["open file", "edit content", "save file", "close file"]for action in actions:history.append(action)print(f"\nLimited history (latest 3 actions): {history}")
Frequently Asked Questions
1. When should I use a deque instead of a list?
Use a deque when you need efficient append and pop operations from both ends of a collection. Lists are only efficient for operations at the right end (append/pop) but inefficient for left-end operations.
2. How do I limit the size of a deque?
Use the `maxlen` parameter when creating the deque: `d = deque(iterable, maxlen=n)`. When the deque reaches this size, adding new items causes items from the opposite end to be removed.
3. Can I access elements in a deque by index?
Yes, deques support index access like `d[0]` and `d[-1]`, but unlike lists, deques are not optimized for random access in the middle. Use index access sparingly with large deques.
4. Is deque FIFO or LIFO in Python?
A deque is neither inherently FIFO nor LIFO, it's a flexible data structure that can be used to implement both patterns. Use `append()` and `popleft()` for FIFO (queue) behavior, or use `append()` and `pop()` for LIFO (stack) behavior.
5. Is deque faster than list?
Yes, for operations at the beginning of the collection. Deques have O(1) time complexity for append and pop operations at both ends, while lists have O(n) time complexity for operations at the beginning. For operations at the end, both have similar performance. For random access by index, lists are generally faster.
6. What is the difference between stack and deque?
A stack is a LIFO (Last In, First Out) data structure with operations typically limited to pushing and popping elements from one end. A deque (double-ended queue) is a more flexible data structure that allows efficient insertion and removal at both ends. A deque can be used to implement a stack, but it offers additional functionality that a traditional stack does not have.
Contribute to Docs
- Learn more about how to get involved.
- Edit this page on GitHub to fix an error or make an improvement.
- Submit feedback to let us know how we can improve Docs.
Learn Python on Codecademy
- Career path
Computer Science
Looking for an introduction to the theory behind programming? Master Python while learning data structures, algorithms, and more!Includes 6 CoursesWith Professional CertificationBeginner Friendly75 hours - Course
Learn Python 3
Learn the basics of Python 3.12, one of the most powerful, versatile, and in-demand programming languages today.With CertificateBeginner Friendly23 hours