What are Stacks and Queues?
Stacks and queues are linear data structures that only usually support push, pop, and peek operations, with no random access. Items must be traversed sequentially.
- Stack: An ordered collection of items where new items are added and existing items removed from the same end (top). (LIFO: Last in, first out)
- Queue: An ordered collection of items where new items are added to the rear, and existing items removed from the front. (FIFO: First-in first-out.)
This guide walks you through everything you need to know about the stack, queue, and deque data structures, with clear, commented code samples.
- Properties of a stack
- Properties of a queue
- Big O time complexity of operations
- Pros and cons of stacks
- Pros and cons of queues
- Create a stack in Python
- Create a queue in Python
- What is a deque?
- Create a deque in Python
- Stack and queue problems
Properties of a Stack
- Items that are closer to the base of the stack have been there the longest
- Think of as a stack of plates
- Can only add and remove to top of stack
- LIFO (Last in, first out)
- Can build with either arrays or linked lists
- Cache locality can make arrays faster for search
- If not dynamic array, could be more expensive to grow it
- e.g. Browser history back and forward buttons
Properties of a Queue
- Items that are closer to the front of the queue have been there the longest
- FIFO (First in, first out)
- Usually don’t lookup in a queue
- Best implemented with a linked list. Faster to remove items without shift
- e.g. Printer queue of documents to be printed, or a queue of people
Big O Time Complexity
Stacks
- lookup: O(n)
- pop: O(1)
- push: O(1)
- peek: O(1)
Queues
- lookup: O(n)
- enqueue: O(1)
- dequeue: O(1)
- peek: O(1)
Pros and Cons of Stacks
Pros:
- Fast Operations
- Fast Peek
- Ordered
Cons:
- Slow Lookup
Pros and Cons of Queues
Queues share the same pros and cons as stacks.
Create a Stack in Python
class Stack: def __init__(self): """ Attributes: items: A Python list to hold items in the stack. """ self.items = [] def push(self, item): """Adds a new item to the top of the stack. Args: item: The new item being added to the stack. """ self.items.append(item) def pop(self): """Removes an item from the top of the stack. Returns: If items exist in stack, the item being removed from the stack. If no items exist, IndexError. """ if self.is_empty(): raise IndexError("Stack is empty.") return self.items.pop() def peek(self): """Displays the item current at the top of the stack. Returns: If items exist in stack, the value at the top of the stack. If no items exist, IndexError. """ if self.is_empty(): raise IndexError("Stack is empty.") return self.items[-1] def is_empty(self): """Checks if the stack is currently empty. Returns: True if stack is empty. False if stack contains items. """ return self.items == [] def size(self): """Display a count of how many items are in the stack. Returns: Integer value representing the count of items in the stack. """ return len(self.items)
Create a Queue in Python
class Queue: def __init__(self): """ Attributes: items: A Python list to hold items in the queue. """ self.items = [] def enqueue(self, item): """Adds a new item to the back of the queue. Args: item: The new item being added to the queue. """ self.items.insert(0, item) def dequeue(self): """Removes an item from the front of the queue. Returns: If items exist in queue, the item being removed from the queue. If no items exist, IndexError. """ if self.is_empty(): raise IndexError("Queue is empty.") return self.items.pop() def peek(self): """Displays the item current at the front of the queue. Returns: If items exist in queue, the value at the front of the queue. If no items exist, IndexError. """ if self.is_empty(): raise IndexError("Queue is empty.") return self.items[0] def is_empty(self): """Checks if the queue is currently empty. Returns: True if queue is empty. False if queue contains items. """ return self.items == [] def size(self): """Display a count of how many items are in the queue. Returns: Integer value representing the count of items in the queue. """ return len(self.items)
What is a Deque?
A deque is a double-ended queue, where items can be added and removed from the left or right.
Python includes deques as part of its collections module:
from collections import deque
It’s also possible to create our own deque class using a list.
Create a Deque in Python
class Deque: def __init__(self): """ Attributes: items: A Python list to hold items in the deque. """ self.items = [] def add_right(self, item): """Adds a new item to the right of the queue. Args: item: The new item being added to the queue. """ self.items.append(item) def add_left(self, item): """Adds a new item to the left of the deque. Args: item: The new item being added to the deque. """ self.items.insert(0, item) def remove_right(self): """Removes an item from the right of the deque. Returns: If items exist in queue, the item being removed from the deque. If no items exist, IndexError. """ if self.is_empty(): raise IndexError("Deque is empty.") return self.items.pop() def remove_left(self): """Removes an item from the left of the deque. Returns: If items exist in deque, the item being removed from the deque. If no items exist, IndexError. """ if self.is_empty(): raise IndexError("Deque is empty.") return self.items.pop(0) def size(self): """Display a count of how many items are in the deque. Returns: Integer value representing the count of items in the deque. """ return len(self.items) def is_empty(self): """Checks if the deque is currently empty. Returns: True if deque is empty. False if queue contains items. """ return self.items == []
Stack and Queue Problems
Problem 1:
Implement a queue using two stacks. (Leetcode: 232)
Solution 1:
class QueueWithStacks: def __init__(self): """ Attributes: in_stack: A Python list to hold new items. out_stack: A Python list to hold items to be removed. """ self.in_stack = [] self.out_stack = [] def enqueue(self, item): """Adds a new item to the queue. A new item is added to the top of the in_stack. Args: item: The new item being added to the queue. """ self.in_stack.append(item) def dequeue(self): """Removes an item from the queue. If items in out_stack, return the top item from out_stack. If out_stack is empty, move all items from in_stack to out_stack. If out_stack and in_stack both empty, raise error. Returns: Oldest item in the queue (top item in out_stack). """ if len(self.out_stack) == 0: # Move items from in_stack to out_stack while len(self.in_stack) > 0: in_stack_item = self.in_stack.pop() self.out_stack.append(in_stack_item) # Raise error if out_stack empty if len(self.out_stack) == 0: raise IndexError("Queue is empty.") return self.out_stack.pop()