Heap Implementation in Java

In Java, Heap is a special type of data structure where the root node or parent node is compared with its left and right children and arranged according to the order. Suppose, x is a root node and y is the child node, property key(x)<= key(y) will generate min-heap, and that relation is referred to as "Heap Property".

Based on the order of the parent and child nodes, Heap can be classified in two forms, i.e., Min heap and Max heap. Let's understand both of them one by one and implement the code in Java.

Operations of Heap

Insertion: Add the new element at the end of the heap (array) and then "heapify up" to maintain the heap property by comparing the added element with its parent and swapping if necessary until the correct position is found.

Deletion: Remove the root element (minimum for a min heap, maximum for a max heap), replace it with the last element in the heap, and then "heapify down" by comparing the new root with its children and swapping if necessary until the correct position is found.

Heapify: Adjust the heap to maintain the heap property. In heapify-up, the newly added element is compared with its parent and swapped if needed. In heapify-down, the root element is compared with its children and swapped if needed. This process ensures the heap remains a valid min or max heap.

Min heap

Min heap is a special type of heap data structure that is a complete binary tree in itself. Min heap has the following properties:

  1. Root node value is always smaller in comparison to the other nodes of the heap.
  2. Each internal node has a key value that is always smaller or equal to its children.

We can perform the following three operations in Min heap:

insertNode()

We can perform insertion in the Min heap by adding a new key at the end of the tree. If the value of the inserted key is smaller than its parent node, we have to traverse the key upwards for fulfilling the heap property. The insertion process takes O(log n) time.

extractMin()

It is one of the most important operations which we perform to remove the minimum value node, i.e., the root node of the heap. After removing the root node, we have to make sure that heap property should be maintained. The extractMin() operation takes O(Logn) time to remove the minimum element from the heap.

getMin()

The getMin() operation is used to get the root node of the heap, i.e., minimum element in O(1) time.

Example:

Heap implementation in Java

Min heap Algorithm

MinHeapJavaImplementation.java

Output:

Heap implementation in Java

Using Arrays

A min heap is a binary tree where the parent node is always smaller than its child nodes, ensuring the smallest element is at the root. Implementing a min heap in Java using an array allows efficient insertion, deletion, and heapification through simple index arithmetic. This structure is ideal for applications requiring quick access to the minimum element, such as priority queues.

File Name: RefactoredMinHeap.java

Output:

The Min Heap is: [3, 13, 7, 16, 21, 12, 9]
Parent : 3 Left : 13 Right : 7
Parent : 13 Left : 16 Right : 21
Parent : 7 Left : 12 Right : 9

The Min Value is: 3

The Min Heap is: [7, 13, 9, 16, 21, 12, 9]
Parent : 7 Left : 13 Right : 9
Parent : 13 Left : 16 Right : 21
Parent : 9 Left : 12

Max heap

Max heap is another special type of heap data structure that is also a complete binary tree in itself in Java. Max heap has the following properties:

  1. Root node value is always greater in comparison to the other nodes of the heap.
  2. Each internal node has a key value that is always greater or equal to its children.

We can perform the following three operations in Max heap:

insertNode()

We can perform insertion in the Max heap by adding a new key at the end of the tree. If the value of the inserted key is greater than its parent node, we have to traverse the key upwards for fulfilling the heap property. The insertion process takes O(log n) time.

extractMax()

It is one of the most important operations which we perform to remove the maximum value node, i.e., the root node of the heap. After removing the root node, we have to make sure that heap property should be maintained. The extractMax() operation takes O(Log n) time to remove the maximum element from the heap.

getMax()

The getMax() operation is used to get the root node of the heap, i.e., maximum element in O(1) time.

Example:

Heap implementation in Java

Min heap Algorithm

MaxHeapJavaImplementation.java

Output:

Heap implementation in Java

Using Collections.reverseOrder() method via library Functions

The Collections.reverseOrder() method in Java is a powerful utility for reversing the natural ordering of elements in a collection. This method returns a comparator that imposes the reverse of the natural ordering on a collection of objects that implement the Comparable interface. By leveraging this method, developers can easily transform a min-heap into a max-heap, reverse the order of a sorted list, or adjust the priority of elements in a priority queue.

File Name: MaxHeapDemo.java

Output:

Head value using peek function:400
The queue elements:
400
30
20
10
After removing an element with poll function:
30
10
20
After removing 30 with remove function:
20
10
Priority queue contains 20 or not?: true
Values in array: 
Value: 20
Value: 10

Applications of Heap

Priority Queues: Heaps are commonly utilized to implement priority queues, where elements with higher priority are extracted first. This is essential in applications such as task scheduling, interrupt handling, and event processing.

Sorting Algorithms: Heapsort, a comparison-based sorting algorithm, relies on the Heap data structure. It offers a time complexity of O(n log n), making it efficient for sorting large datasets.

Graph Algorithms: Heaps are integral in graph algorithms like Dijkstra's shortest path algorithm, Prim's minimum spanning tree algorithm, and the A* search algorithm.

File Compression: Heaps play a crucial role in data compression techniques such as Huffman coding. Here, a priority queue, typically implemented as a min-heap, constructs a Huffman tree.

Dynamic Programming: Heaps are employed in dynamic programming algorithms, particularly in greedy algorithms where elements are processed based on their priority.

Medical Applications: In medical settings, heaps are used to manage patient information, including vital signs, treatments, and test results, based on their criticality or urgency.

External Sorting: Heaps are employed in external sorting algorithms to efficiently sort large datasets that exceed memory capacity. Chunks of data are processed using a priority queue.

Load Balancing: Heaps are applied in load balancing algorithms to distribute tasks or requests among servers. Tasks are typically processed according to their priority or load.

Online Algorithms: Heaps find application in online algorithms that process data in real-time as it arrives, such as in recommendation systems, event processing, and streaming data management.

Financial Applications: Heaps are utilized in financial applications such as stock market analysis and algorithmic trading, where they manage and process stock data based on priority.

Advantages of Heap

Efficient Insertion and Deletion: The heap structure supports efficient insertion and deletion of elements. When a new element is inserted, it is initially placed at the end of the heap and then moved to its correct position using the heapify operation. Similarly, when an element is removed, it is replaced by the last element in the heap, and the heap is restructured using the heapify operation.

Efficient Priority Queue Implementation: Heaps are commonly used to implement priority queues, where the highest priority element is always located at the top of the heap. This allows for constant-time access to the highest priority element, making heaps a highly efficient data structure for priority queue implementations.

Guaranteed Access to Extreme Values: In a max-heap, the maximum element is always at the root, while in a min-heap, the minimum element is always at the root. This property ensures that the heap provides guaranteed access to the maximum or minimum element, which is useful in algorithms requiring quick access to extreme values.

Space Efficiency: The heap structure is space-efficient as it organizes elements in a complete binary tree, which typically uses less memory compared to other data structures like linked lists or dynamic arrays.

Heap Sort Algorithm: The heap data structure is the foundation of the heap sort algorithm, an efficient sorting method with a worst-case time complexity of O(n log n). This makes heap sort a robust choice for sorting large datasets.

Disadvantages of Heap

Lack of Flexibility: The heap structure is designed to maintain a specific order of elements, which limits its flexibility. This makes it less suitable for applications that require more adaptable data structures.

Inefficient for Searching: While heaps provide efficient access to the top element, they are not ideal for searching for specific elements. Finding an element in a heap involves traversing the entire tree, resulting in a time complexity of O(n).

Instability: Heaps are not stable data structures, meaning that the relative order of elements with equal values may not be preserved during insertion or modification.

Memory Management Challenges: Heaps require dynamic memory allocation, which can be problematic in systems with limited memory resources. Additionally, managing the allocated memory for heaps can be complex and prone to errors.

Complexity Considerations: Although heaps allow efficient insertion, deletion, and priority queue operations, the worst-case time complexity is O(n log n). This may not be optimal for applications that need faster algorithms.