• Skip to primary navigation
  • Skip to main content
  • Skip to footer

In Out Code

Your comprehensive guide to optimized code

  • Data Structures
  • Python
    • Control Flow
    • HackerRank
    • Input and Output
    • Modules
  • AWS

Stacks, Queues and Deques Data Structure Guide

You are here: Home / Data Structures / Stacks, Queues and Deques Data Structure Guide

August 20, 2019 by Daniel Andrews

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()

Category iconData Structures Tag iconData Structure Guide,  Deques,  Queues,  Stacks

About Daniel Andrews

Passionate about all things data and cloud. Specializing in Python, AWS and DevOps, with a Masters degree in Data Science from City University, London, and a BSc in Computer Science.

Footer

Recent Posts

  • How to Setup Neo4j on AWS ECS (EC2)
  • How to Setup Neo4j on AWS EC2
  • How to List AWS S3 Bucket Names and Prefixes
  • Amazon Redshift Tutorial (AWS)
  • Big O: How to Calculate Time and Space Complexity

.