All topics

Queues

A queue is an abstract data type that uses a principle called First-In-First-Out (FIFO), meaning that the first object added to the queue must be the first object removed from it. You can analogize this to a checkout line at a store where the line only moves forward when the person at the head of it has been helped, and each person in the line is directly behind the person whose arrival immediately preceded theirs.

At minimum, any queue should be able to perform the following two operations:

  • Enqueue: Add an object to the back of the line.
  • Dequeue: Remove the object at the head of the line and return it; the element that was previously second in line is now at the head of the line.

The diagram below demonstrates these simple operations on an empty queue:

queue.png

In addition, it's often helpful to implement a method to check whether or not a queue is empty to ensure you are not attempting to perform dequeue operations on an empty queue.

Sample Java Implementation

EXAMPLE
The code below demonstrates a simple Java Queue implementation.
import java.util.*;

class Queue<E> {
    
    private class Element<E> {
        // The data value of the element
        private E data;
        // The next element in the queue
        private Element<E> next;
        
        Element(E data) {
            this.data = data;
            this.next = null;
        }
    }
    
    // The first element in the queue
    private Element<E> front;
    // The last element in the queue
    private Element<E> back;
    
    /** Create an empty queue **/
    public Queue() {
        this.front = null;
        this.back = null;
    }
    
    /** @return true if the queue is empty, false if it is not.
    **/
    public boolean isEmpty() {
        return front == null || back == null;
    }
    
    /**
        Enqueues a value into the queue. 
        @param value The data to be enqueued.
    **/
    public void enqueue(E value) {
        // Create new element
        Element<E> newElement = new Element<E>(value);
        
        // If the queue is empty
        if(isEmpty()) {
            this.front = newElement;
        }
        else { // Queue is not empty
            // Link the old last element to the new last element
            this.back.next = newElement;
        }
        
        // Set new back element regardless of whether or not queue is empty
        this.back = newElement;
    }
    
    /**
        Dequeues the queue's first element.
        @return the data associated with the queue's dequeued element.
        @throws NoSuchElementException if the queue contains no elements.
    **/
    public E dequeue() {
        if(isEmpty()) {
            throw new NoSuchElementException();
        }
        
        Element<E> head = front;
        this.front = front.next;
        
        return head.data;
    }
    
    /** 
        'View' the element at the front of the queue.
        @return the data associated with the queue's first element.
        @throws NoSuchElementException if the queue contains no elements.
    **/
    public E peekFirst() {
        if(isEmpty()) {
            throw new NoSuchElementException();
        }
        
        return front.data;
    }
    
    /** 
        'View' the element at the tail of the queue.
        @return the data associated with the queue's first element.
        @throws NoSuchElementException if the queue contains no elements.
    **/
    public E peekLast() {
        if(isEmpty()) {
            throw new NoSuchElementException();
        }
        
        return back.data;
    }
}

class QueueDemo {
    public static void main(String[] args) {
        Queue<Integer> intQueue = new Queue<Integer>();
        
        try {
            intQueue.dequeue();
        }
        catch(NoSuchElementException e) {
            System.out.println("We cannot dequeue from an empty queue.");
        }
        
        for(int i = 0; i < 4; i++) {
            intQueue.enqueue(i);
            System.out.println(
                "First: " + intQueue.peekFirst() + 
                "; Last: " + intQueue.peekLast()
            );
        }
        for(int i = 0; i < 4; i++) {
            System.out.println("Dequeued: " + intQueue.dequeue());
        }
        
        try {
            intQueue.peekFirst();
        }
        catch(NoSuchElementException e) {
            System.out.println("We cannot peek at an empty queue.");
        }
    }
}
Run
Output

 
Go to Top

Stacks

A stack is a data structure that uses a principle called Last-In-First-Out (LIFO), meaning that the last object added to the stack must be the first object removed from it.

At minimum, any stack should be able to perform the following three operations:

  • Peek: Return the object at the top of the stack (without removing it).
  • Push: Add an object passed as an argument to the top of the stack.
  • Pop: Remove the object at the top of the stack and return it.

The diagram below demonstrates these simple operations on a stack:

stack.png

In addition, it's often helpful to implement a method to check whether or not a stack is empty to ensure you are not attempting to perform peek or pop operations on an empty stack.

Sample Java Implementation

EXAMPLE
The code below demonstrates a simple Java Stack implementation.

import java.util.*;

class Stack<E> {
    
    private class Element<E> {
        // The data value of the element
        private E data;
        // The next element in the stack
        private Element<E> next;
        
        Element(E data) {
            this.data = data;
            this.next = null;
        }
    }
    
    // The element at the top of the stack
    private Element<E> top;
    
    /** Create an empty stack **/
    public Stack() {
        this.top = null;
    }
    
    /** @return true if the stack is empty, false if it is not.
    **/
    public boolean isEmpty() {
        return top == null;
    }
    
    /**
        Pushes a value onto the top of the stack. 
        @param value The data for the stack's new top element.
    **/
    public void push(E value) {
        // Create new top element
        Element<E> newTop = new Element<E>(value);
        
        // If the stack is not empty
        if(!isEmpty()) {
            // Set old top's next variable to point to new top
            newTop.next = top;
        }
        
        // Set new top regardless of whether or not stack is empty
        this.top = newTop;
    }
    
    /**
        Remove the element at the top of the stack.
        @return the data associated with the stack's topmost element being removed.
        @throws EmptyStackException if the stack contains no elements.
    **/
    public E pop() {
        if(isEmpty()) {
            throw new EmptyStackException();
        }
        
        Element<E> oldTop = top;
        this.top = top.next;
        
        return oldTop.data;
    }
    
    /** 
        'View' the element at the top of the stack.
        @return the data associated with the stack's topmost element.
        @throws EmptyStackException if the stack contains no elements.
    **/
    public E peek() {
        if(isEmpty()) {
            throw new EmptyStackException();
        }
        
        return top.data;
    }
}

class StackDemo {
    public static void main(String[] args) {
        Stack<Integer> intStack = new Stack<Integer>();
        
        try {
            intStack.pop();
        }
        catch(EmptyStackException e) {
            System.out.println("We cannot pop off an empty stack.");
        }
        
        for(int i = 0; i < 4; i++) {
            intStack.push(i);
            System.out.println("New Top: " + intStack.peek());
        }
        for(int i = 0; i < 4; i++) {
            System.out.println("Popped: " + intStack.pop());
        }
        
        try {
            intStack.peek();
        }
        catch(EmptyStackException e) {
            System.out.println("We cannot peek at an empty stack.");
        }
    }
}
Run
Output

 
Related challenge for Stacks
Go to Top
  1. Challenge Walkthrough
    Let's walk through this sample challenge and explore the features of the code editor.1 of 6
  2. Review the problem statement
    Each challenge has a problem statement that includes sample inputs and outputs. Some challenges include additional information to help you out.2 of 6
  3. Choose a language
    Select the language you wish to use to solve this challenge.3 of 6
  4. Enter your code
    Code your solution in our custom editor or code in your own environment and upload your solution as a file.4 of 6
  5. Test your code
    You can compile your code and test it for errors and accuracy before submitting.5 of 6
  6. Submit to see results
    When you're ready, submit your solution! Remember, you can go back and refine your code anytime.6 of 6
  1. Check your score