Heap implementation in Java
Last Updated :
27 May, 2024
A heap is a binary tree-based data structure that adheres to a heap property. In a heap, every parent node has a specific relationship with its children: in a max-heap, each parent is greater than or equal to its children, while in a min-heap, each parent is less than or equal to its children. Heaps are commonly used to implement priority queues and are foundational for algorithms like heap-sort and Dijkstra's algorithm.
Organization of Heaps
Heaps are often implemented using arrays, leveraging the binary tree structure. The heap is typically visualized as a binary tree where
- The root is at index 0
- For any node at index i its left child is at index 2*i + 1 its right child is at index 2*i + 2 and its parent is at index (i - 1) / 2
Heap Diagram:
Here is a min-heap structure represented as both a tree and an array
Min-Heap as Tree:

Min-Heap as Array:
[5, 10, 15, 20, 25, 30, 35]
Heap Implementation in Java:
To implement a heap in Java, you need to consider the operations required to maintain the heap property. Key operations include.
- insert: Adds a new element and restores the heap property.
- extract: Removes and returns the root element, then restores the heap property.
- heapify: Re-balances the heap after an operation.
Basic Operations:
Operation
| Algorithm
| Complexity
|
---|
Insert
| - Insert the new element at the end of the heap (the next available index in the array).
- Bubble up the element to its correct position by comparing it with its parent until the heap property is restored.
| - Time complexity: O(log n)
|
---|
Extract
| - Swap the root with the last element, then remove the last element (the original root).
- Restore the heap property by "bubbling down" the new root until it finds the correct position.
| - Time complexity: O(log n)
|
---|
Heapify
| - Given an array, this operation ensures it follows the heap property.
- Start from the last non-leaf node and bubble down to maintain the heap structure.
| - Time complexity: O(n). This is because half of the nodes are leaves and require little or no adjustment.
|
---|
Java Code To Implementation Min Heap
A Min Heap is a type of binary heap where the parent node is always less than or equal to its child nodes. This property must hold for every node in the heap. The smallest element is always at the root of the heap. A min heap is a complete binary tree, meaning all levels of the tree are fully filled except possibly the last level, which is filled from left to right.
Example:
Java
// Java Program to Implement Min Heap
import java.util.ArrayList;
class MinHeap {
private ArrayList<Integer> heap;
// Constructor to initialize the heap
public MinHeap() {
heap = new ArrayList<>();
}
// Returns the index of the parent node
private int parent(int i) {
return (i - 1) / 2;
}
// Returns the index of the left child node
private int leftChild(int i) {
return 2 * i + 1;
}
// Returns the index of the right child node
private int rightChild(int i) {
return 2 * i + 2;
}
// Swaps the elements at indices i and j
private void swap(int i, int j) {
int temp = heap.get(i);
heap.set(i, heap.get(j));
heap.set(j, temp);
}
// Inserts a new value into the heap
public void insert(int value) {
// Add the new value at the end of the heap
heap.add(value);
// Get the index of the newly added value
int currentIndex = heap.size() - 1;
// Bubble up to restore heap property
while (currentIndex > 0 && heap.get(currentIndex) < heap.get(parent(currentIndex))) {
// Swap with parent if current value is less
swap(currentIndex, parent(currentIndex));
// Move up to the parent index
currentIndex = parent(currentIndex);
}
}
// Extracts and returns the minimum value from the heap
public int extractMin() {
if (heap.isEmpty()) {
throw new RuntimeException("Heap is empty");
}
// The minimum value is at the root
int min = heap.get(0);
// Remove the last element
int lastElement = heap.remove(heap.size() - 1);
if (!heap.isEmpty()) {
// Move the last element to the root
heap.set(0, lastElement);
// Bubble down to restore heap property
int currentIndex = 0;
while (true) {
int left = leftChild(currentIndex);
int right = rightChild(currentIndex);
int smallest = currentIndex;
// Find the smallest value among current, left child, and right child
if (left < heap.size() && heap.get(left) < heap.get(smallest)) {
smallest = left;
}
if (right < heap.size() && heap.get(right) < heap.get(smallest)) {
smallest = right;
}
if (smallest == currentIndex) {
// Heap property is restored
break;
}
// Swap with the smallest child
swap(currentIndex, smallest);
// Move down to the smallest child's index
currentIndex = smallest;
}
}
// Return the minimum value
return min;
}
// Checks if the heap is empty
public boolean isEmpty() {
return heap.isEmpty();
}
}
public class HeapExample {
public static void main(String[] args) {
MinHeap minHeap = new MinHeap();
// Insert values into the min heap
minHeap.insert(10);
minHeap.insert(5);
minHeap.insert(15);
minHeap.insert(20);
minHeap.insert(25);
// Extract and print the minimum values from the heap
System.out.println("Extracted Min: " + minHeap.extractMin());
System.out.println("Extracted Min: " + minHeap.extractMin());
}
}
OutputExtracted Min: 5
Extracted Min: 10
Java Code To Implementation Max Heap
A Max Heap is a type of binary heap where the parent node is always greater than or equal to its child nodes. This property must hold for every node in the heap. The largest element is always at the root of the heap. A max heap is a complete binary tree, meaning all levels of the tree are fully filled except possibly the last level, which is filled from left to right.
Below is the Program Implementing the Max Heap:
Java
// Java Program to Implement Max Heap
import java.util.ArrayList;
class MaxHeap {
private ArrayList<Integer> heap;
// Constructor to initialize the heap
public MaxHeap() {
heap = new ArrayList<>();
}
// Returns the index of the parent node
private int parent(int i) {
return (i - 1) / 2;
}
// Returns the index of the left child node
private int leftChild(int i) {
return 2 * i + 1;
}
// Returns the index of the right child node
private int rightChild(int i) {
return 2 * i + 2;
}
// Swaps the elements at indices i and j
private void swap(int i, int j) {
int temp = heap.get(i);
heap.set(i, heap.get(j));
heap.set(j, temp);
}
// Inserts a new value into the heap
public void insert(int value) {
// Add the new value at the end of the heap
heap.add(value);
// Get the index of the newly added value
int currentIndex = heap.size() - 1;
// Bubble up to restore heap property
while (currentIndex > 0 && heap.get(currentIndex) > heap.get(parent(currentIndex))) {
// Swap with parent if current value is greater
swap(currentIndex, parent(currentIndex));
// Move up to the parent index
currentIndex = parent(currentIndex);
}
}
// Extracts and returns the maximum value from the heap
public int extractMax() {
if (heap.isEmpty()) {
throw new RuntimeException("Heap is empty");
}
// The maximum value is at the root
int max = heap.get(0);
// Remove the last element
int lastElement = heap.remove(heap.size() - 1);
if (!heap.isEmpty()) {
// Move the last element to the root
heap.set(0, lastElement);
// Bubble down to restore heap property
int currentIndex = 0;
while (true) {
int left = leftChild(currentIndex);
int right = rightChild(currentIndex);
int largest = currentIndex;
// Find the largest value among current, left child, and right child
if (left < heap.size() && heap.get(left) > heap.get(largest)) {
largest = left;
}
if (right < heap.size() && heap.get(right) > heap.get(largest)) {
largest = right;
}
if (largest == currentIndex) {
// Heap property is restored
break;
}
// Swap with the largest child
swap(currentIndex, largest);
// Move down to the largest child's index
currentIndex = largest;
}
}
// Return the maximum value
return max;
}
// Checks if the heap is empty
public boolean isEmpty() {
return heap.isEmpty();
}
}
public class HeapExample {
public static void main(String[] args) {
MaxHeap maxHeap = new MaxHeap();
// Insert values into the max heap
maxHeap.insert(10);
maxHeap.insert(5);
maxHeap.insert(15);
maxHeap.insert(20);
maxHeap.insert(25);
// Extract and print the maximum values from the heap
System.out.println("Extracted Max: " + maxHeap.extractMax());
System.out.println("Extracted Max: " + maxHeap.extractMax());
}
}
OutputExtracted Max: 25
Extracted Max: 20
Applications of Heaps
- Priority Queues: Heaps are the underlying data structure for efficient priority queue operations.
- Heap Sort: A sorting algorithm that leverages the heap property.
- Graph Algorithms: Dijkstra's algorithm and Prim's algorithm use heaps for efficient vertex extraction.
- Median Maintenance: In scenarios where the median needs to be maintained dynamically.
Conclusion
Heaps are versatile data structures with wide-ranging applications. Their efficient insertion and extraction operations make them ideal for implementing priority queues and optimizing graph algorithms. With a clear understanding of how heaps are structured and implemented in Java, you can leverage them in various problem-solving scenarios.