2. Priority Queues

Overview

  • A priority queue is a data structure in which only the highest priority item is accessible.
    • In computer science, a heap is used as the basis of a very efficient algorithm for sorting arrays, called heapsort (we'll cover later).
    • The heap is also used to implement a special kind of queue called a priority queue. However, the heap is not very useful as an abstract data type (ADT) on its own. Consequently, we will not create a Heap interface or code a class that implements it.
    • Instead we will incorporate its algorithms when we implement a priority queue class and heapsort.

Class java.util.PriorityQueue<E>

Constructor Description
PriorityQueue() Creates a PriorityQueue with the default initial capacity (11) that orders its elements according to their natural ordering.
PriorityQueue(Comparator<? super E> comparator) Creates a PriorityQueue with the default initial capacity and whose elements are ordered according to the specified comparator.
Modifier and Type Method Description
boolean add(E e) Inserts the specified element into this priority queue.
void clear() Removes all of the elements from this priority queue.
Comparator<? super E> comparator() Returns the comparator used to order the elements in this queue, or null if this queue is sorted according to the natural ordering of its elements.
boolean contains(Object o) Returns true if this queue contains the specified element.
Iterator<E> iterator() Returns an iterator over the elements in this queue.
boolean offer(E e) Inserts the specified element into this priority queue.
E peek() Retrieves, but does not remove, the head of this queue, or returns null if this queue is empty.
E poll() Retrieves and removes the head of this queue, or returns null if this queue is empty.
boolean remove(Object o) Removes a single instance of the specified element from this queue, if it is present.
int size() Returns the number of elements in this collection.
  • The class java.util.PriorityQueue uses an array of type Object[] for heap storage.

Class PriorityQueue<E>

  • In our case, as an example, we use ArrayList for implementing a PriorityQueue class.
Data Field/Attribute Description
ArrayList<E> theData An ArrayList to hold the data
Comparator<E> comparator An optional object that implements the Comparator<E> interface by providing a compare method
Constructor Description
KWPriorityQueue() Constructs a heap-based priority queue that uses the elements' natural ordering
KWPriorityQueue(Comparator<E> comp) Constructs a heap-based priority queue that uses the compare method of Comparator comp to determine the ordering of the elements
Private Method Description
private int compare(E left, E right) Compares two objects and returns a negative number if object left is less than object right, zero if they are equal, and a positive number if object left is greater than object right
private void swap(int i, int j) Exchanges the object references in theData at indexes i and j
package datastructures.heap;

import java.util.*;

/** The PriorityQueue implements the Queue interface
 by building a heap in an ArrayList. The heap is structured
 so that the “smallest” item is at the top.
 */

public class PriorityQueue<E> extends AbstractQueue<E> implements Queue<E> {
// Data Fields
    /**
     * The ArrayList to hold the data.
     */
    private ArrayList<E> data;
    /**
     * An optional reference to a Comparator object.
     */
    Comparator<E> comparator = null;

    // Methods
// Constructor
    public PriorityQueue() {
        data = new ArrayList<>();
    }

    /** Creates a heap‐based priority queue with the specified initial
     capacity that orders its elements according to the specified
     comparator.
     @param capacity The initial capacity for this priority queue
     @param comp The comparator used to order this priority queue
     @throws IllegalArgumentException if capacity is less than 1
     */
    public PriorityQueue(int capacity, Comparator<E> comp) {
        if (capacity < 1)
            throw new IllegalArgumentException();
        data = new ArrayList<>();
        comparator = comp;
    }

    /**
     * Insert an item into the priority queue.
     * pre: The ArrayList theData is in heap order.
     * post: The item is in the priority queue and
     * theData is in heap order.
     *
     * @param item The item to be inserted
     * @throws NullPointerException if the item to be inserted is null.
     */
    @Override
    public boolean offer(E item) {
        // Add the item to the heap.
        data.add(item);
        // child is newly inserted item.
        int child = data.size()-1;
        int parent = (child - 1) /2; // Find child's parent.
        // Reheap
        while (parent >= 0 && compare(data.get(parent),
                data.get(child)) > 0) {
            swap(parent, child);
            child = parent;
            parent = (child - 1) /2;
        }
        return true;
    }

    /**
     * Remove an item from the priority queue
     * pre: The ArrayList theData is in heap order.
     * post: Removed smallest item, theData is in heap order.
     *
     * @return The item with the smallest priority value or null if empty.
     */
    @Override
    public E poll() {
        if (isEmpty()) {
            return null;
        }
        // Save the top of the heap.
        E result = data.get(0);
        // If only one item then remove it.
        if (data.size() == 1) {
            data.remove(0);
            return result;
        }
        /* Remove the last item from the ArrayList and place it into the first position. */
        data.set(0, data.remove(data.size() - 1));
        // The parent starts at the top.
        int parent = 0;
        while (true) {
            int leftChild = 2 * parent + 1;
            if (leftChild >= data.size()) {
                break; // Out of heap.
            }
            int rightChild = leftChild + 1;
            int minChild = leftChild; // Assume leftChild is smaller.
            // See whether rightChild is smaller.
            if (rightChild < data.size()
                    && compare(data.get(leftChild),
                    data.get(rightChild)) > 0) {
                minChild = rightChild;
            }
            // assert: minChild is the index of the smaller child.
            // Move smaller child up heap if necessary.
            if (compare(data.get(parent),
                    data.get(minChild)) > 0) {
                swap(parent, minChild);
                parent = minChild;
            } else { // Heap property is restored.
                break;
            }
        }
        return result;
    }

    @Override
    public E peek() {
        return data.get(0);
    }

    /** Compare two items using either a Comparator object's compare method
     or their natural ordering using method compareTo.
     @pre: If comparator is null, left and right implement Comparable<E>.
     @param left One item
     @param right The other item
     @return Negative int if left less than right,
     0 if left equals right,
     positive int if left > right
     @throws ClassCastException if items are not Comparable
     */
    @SuppressWarnings("unchecked")
    private int compare(E left, E right) {
        if (comparator != null) {
            // A Comparator is defined.
            return comparator.compare(left, right);
        } else {
            // Use left's compareTo method.
            return ((Comparable<E>) left).compareTo(right);
        }
    }

    @Override
    public Iterator<E> iterator() {
        return null;
    }

    @Override
    public int size() {
        return data.size();
    }

    private void swap(int index1, int index2) {
        E temp = data.get(index1);
        data.set(index1, data.get(index2));
        data.set(index2, temp);
    }
}