Using Java’s Priority Queue as Min-Heap and Max-Heap

Introduction

The Java util package provides a versatile data structure known as the PriorityQueue. This is essentially an implementation of a priority queue using a binary heap. By default, it works as a min-heap, but by passing a custom comparator, it can function as a max-heap. In this guide, we’ll explore the nuances of using the PriorityQueue for various types of objects.

Basics of PriorityQueue

A PriorityQueue is used when objects are supposed to be processed based on their priority. The elements of the priority queue are ordered according to their natural ordering or by a Comparator provided at the time of queue construction.

import java.util.PriorityQueue;

PriorityQueue<Integer> minHeap = new PriorityQueue<>();
minHeap.add(10);
minHeap.add(5);
minHeap.add(20);

int top = minHeap.poll();  // Retrieves and removes the smallest number, which is 5

For Max-Heap

To transform the natural behavior of the PriorityQueue from a min-heap to a max-heap, you can pass a custom comparator:

PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
maxHeap.add(10);
maxHeap.add(5);
maxHeap.add(20);

int top = maxHeap.poll();  // Retrieves and removes the largest number, which is 20

Handling Strings

For Strings, the natural order is lexicographic. However, you can also change the order using a custom comparator.

PriorityQueue<String> stringQueue = new PriorityQueue<>();
stringQueue.add("banana");
stringQueue.add("apple");
stringQueue.add("cherry");

String first = stringQueue.poll();  // "apple"

// For reverse lexicographic order:
PriorityQueue<String> reverseQueue = new PriorityQueue<>(Comparator.reverseOrder());

Custom Objects in PriorityQueue

To use custom objects in a PriorityQueue, you’ll need to either make the objects Comparable or provide an external Comparator.

Let’s consider a class Task:

public class Task {
    int priority;
    String description;

    public Task(int priority, String description) {
        this.priority = priority;
        this.description = description;
    }

    public int getPriority() {
        return priority;
    }

    // ... other getters and setters ...
}

If you want the PriorityQueue to order the tasks by their priority:

PriorityQueue<Task> taskQueue = new PriorityQueue<>(Comparator.comparingInt(Task::getPriority));
taskQueue.add(new Task(5, "Do laundry"));
taskQueue.add(new Task(1, "Pay bills"));
taskQueue.add(new Task(3, "Buy groceries"));

Task nextTask = taskQueue.poll();  // Retrieves the task with priority 1: "Pay bills"

To reverse the order, you can use:

PriorityQueue<Task> taskQueueReverse = new PriorityQueue<>(Comparator.comparingInt(Task::getPriority).reversed());

Leave a Comment

Your email address will not be published. Required fields are marked *