diff --git a/DIRECTORY.md b/DIRECTORY.md
index 2a6bf70c7632..ee1b9dcd8b11 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -833,6 +833,7 @@
* [FibonacciHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/FibonacciHeapTest.java)
* [GenericHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java)
* [LeftistHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java)
+ * [MinPriorityQueueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MinPriorityQueueTest.java)
* lists
* [CircleLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CircleLinkedListTest.java)
* [CountSinglyLinkedListRecursionTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CountSinglyLinkedListRecursionTest.java)
diff --git a/src/main/java/com/thealgorithms/datastructures/heaps/MinPriorityQueue.java b/src/main/java/com/thealgorithms/datastructures/heaps/MinPriorityQueue.java
index 9d19e9aaee1a..a1360b14dc5a 100644
--- a/src/main/java/com/thealgorithms/datastructures/heaps/MinPriorityQueue.java
+++ b/src/main/java/com/thealgorithms/datastructures/heaps/MinPriorityQueue.java
@@ -1,16 +1,23 @@
package com.thealgorithms.datastructures.heaps;
/**
- * Minimum Priority Queue It is a part of heap data structure A heap is a
- * specific tree based data structure in which all the nodes of tree are in a
- * specific order. that is the children are arranged in some respect of their
- * parents, can either be greater or less than the parent. This makes it a min
- * priority queue or max priority queue.
+ * A MinPriorityQueue is a specialized data structure that maintains the
+ * min-heap property, where the smallest element has the highest priority.
*
- *
+ *
In a min-priority queue, every parent node is less than or equal
+ * to its child nodes, which ensures that the smallest element can
+ * always be efficiently retrieved.
*
- *
- * Functions: insert, delete, peek, isEmpty, print, heapSort, sink
+ *
Functions:
+ *
+ * - insert(int key): Inserts a new key into the queue.
+ * - delete(): Removes and returns the highest priority value (the minimum).
+ * - peek(): Returns the highest priority value without removing it.
+ * - isEmpty(): Checks if the queue is empty.
+ * - isFull(): Checks if the queue is full.
+ * - heapSort(): Sorts the elements in ascending order.
+ * - print(): Prints the current elements in the queue.
+ *
*/
public class MinPriorityQueue {
@@ -18,18 +25,25 @@ public class MinPriorityQueue {
private final int capacity;
private int size;
- // class the constructor and initializes the capacity
- MinPriorityQueue(int c) {
+ /**
+ * Initializes a new MinPriorityQueue with a specified capacity.
+ *
+ * @param c the maximum number of elements the queue can hold
+ */
+ public MinPriorityQueue(int c) {
this.capacity = c;
this.size = 0;
this.heap = new int[c + 1];
}
- // inserts the key at the end and rearranges it
- // so that the binary heap is in appropriate order
+ /**
+ * Inserts a new key into the min-priority queue.
+ *
+ * @param key the value to be inserted
+ */
public void insert(int key) {
if (this.isFull()) {
- return;
+ throw new IllegalStateException("MinPriorityQueue is full. Cannot insert new element.");
}
this.heap[this.size + 1] = key;
int k = this.size + 1;
@@ -44,89 +58,98 @@ public void insert(int key) {
this.size++;
}
- // returns the highest priority value
+ /**
+ * Retrieves the highest priority value (the minimum) without removing it.
+ *
+ * @return the minimum value in the queue
+ * @throws IllegalStateException if the queue is empty
+ */
public int peek() {
+ if (isEmpty()) {
+ throw new IllegalStateException("MinPriorityQueue is empty. Cannot peek.");
+ }
return this.heap[1];
}
- // returns boolean value whether the heap is empty or not
+ /**
+ * Checks whether the queue is empty.
+ *
+ * @return true if the queue is empty, false otherwise
+ */
public boolean isEmpty() {
- return 0 == this.size;
+ return size == 0;
}
- // returns boolean value whether the heap is full or not
+ /**
+ * Checks whether the queue is full.
+ *
+ * @return true if the queue is full, false otherwise
+ */
public boolean isFull() {
- return this.size == this.capacity;
+ return size == capacity;
}
- // prints the heap
+ /**
+ * Prints the elements of the queue.
+ */
public void print() {
- for (int i = 1; i <= this.capacity; i++) {
+ for (int i = 1; i <= this.size; i++) {
System.out.print(this.heap[i] + " ");
}
System.out.println();
}
- // heap sorting can be done by performing
- // delete function to the number of times of the size of the heap
- // it returns reverse sort because it is a min priority queue
+ /**
+ * Sorts the elements in the queue using heap sort.
+ */
public void heapSort() {
- for (int i = 1; i < this.capacity; i++) {
+ for (int i = 1; i <= this.size; i++) {
this.delete();
}
}
- // this function reorders the heap after every delete function
+ /**
+ * Reorders the heap after a deletion to maintain the heap property.
+ */
private void sink() {
int k = 1;
- while (2 * k <= this.size || 2 * k + 1 <= this.size) {
- int minIndex;
- if (this.heap[2 * k] >= this.heap[k]) {
- if (2 * k + 1 <= this.size && this.heap[2 * k + 1] >= this.heap[k]) {
- break;
- } else if (2 * k + 1 > this.size) {
- break;
- }
+ while (2 * k <= this.size) {
+ int minIndex = k; // Assume current index is the minimum
+
+ if (2 * k <= this.size && this.heap[2 * k] < this.heap[minIndex]) {
+ minIndex = 2 * k; // Left child is smaller
}
- if (2 * k + 1 > this.size) {
- minIndex = this.heap[2 * k] < this.heap[k] ? 2 * k : k;
- } else {
- if (this.heap[k] > this.heap[2 * k] || this.heap[k] > this.heap[2 * k + 1]) {
- minIndex = this.heap[2 * k] < this.heap[2 * k + 1] ? 2 * k : 2 * k + 1;
- } else {
- minIndex = k;
- }
+ if (2 * k + 1 <= this.size && this.heap[2 * k + 1] < this.heap[minIndex]) {
+ minIndex = 2 * k + 1; // Right child is smaller
}
+
+ if (minIndex == k) {
+ break; // No swap needed, heap property is satisfied
+ }
+
+ // Swap with the smallest child
int temp = this.heap[k];
this.heap[k] = this.heap[minIndex];
this.heap[minIndex] = temp;
- k = minIndex;
+
+ k = minIndex; // Move down to the smallest child
}
}
- // deletes the highest priority value from the heap
+ /**
+ * Deletes and returns the highest priority value (the minimum) from the queue.
+ *
+ * @return the minimum value from the queue
+ * @throws IllegalStateException if the queue is empty
+ */
public int delete() {
+ if (isEmpty()) {
+ throw new IllegalStateException("MinPriorityQueue is empty. Cannot delete.");
+ }
int min = this.heap[1];
- this.heap[1] = this.heap[this.size];
- this.heap[this.size] = min;
+ this.heap[1] = this.heap[this.size]; // Move last element to the root
this.size--;
this.sink();
return min;
}
-
- public static void main(String[] args) {
- // testing
- MinPriorityQueue q = new MinPriorityQueue(8);
- q.insert(5);
- q.insert(2);
- q.insert(4);
- q.insert(1);
- q.insert(7);
- q.insert(6);
- q.insert(3);
- q.insert(8);
- q.print(); // [ 1, 2, 3, 5, 7, 6, 4, 8 ]
- q.heapSort();
- q.print(); // [ 8, 7, 6, 5, 4, 3, 2, 1 ]
- }
}
diff --git a/src/test/java/com/thealgorithms/datastructures/heaps/MinPriorityQueueTest.java b/src/test/java/com/thealgorithms/datastructures/heaps/MinPriorityQueueTest.java
new file mode 100644
index 000000000000..8f93bd630aa7
--- /dev/null
+++ b/src/test/java/com/thealgorithms/datastructures/heaps/MinPriorityQueueTest.java
@@ -0,0 +1,87 @@
+package com.thealgorithms.datastructures.heaps;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class MinPriorityQueueTest {
+
+ @Test
+ void testInsertAndPeek() {
+ MinPriorityQueue queue = new MinPriorityQueue(5);
+ queue.insert(10);
+ queue.insert(5);
+ queue.insert(15);
+
+ Assertions.assertEquals(5, queue.peek(), "The minimum element should be 5.");
+ }
+
+ @Test
+ void testDelete() {
+ MinPriorityQueue queue = new MinPriorityQueue(5);
+ queue.insert(10);
+ queue.insert(5);
+ queue.insert(15);
+
+ Assertions.assertEquals(5, queue.delete(), "The deleted minimum element should be 5.");
+ Assertions.assertEquals(10, queue.peek(), "After deletion, the new minimum should be 10.");
+ }
+
+ @Test
+ void testIsEmpty() {
+ MinPriorityQueue queue = new MinPriorityQueue(5);
+ Assertions.assertTrue(queue.isEmpty(), "The queue should be empty initially.");
+
+ queue.insert(10);
+ Assertions.assertFalse(queue.isEmpty(), "The queue should not be empty after insertion.");
+ }
+
+ @Test
+ void testIsFull() {
+ MinPriorityQueue queue = new MinPriorityQueue(2);
+ queue.insert(10);
+ queue.insert(5);
+
+ Assertions.assertTrue(queue.isFull(), "The queue should be full after inserting two elements.");
+ queue.delete();
+ Assertions.assertFalse(queue.isFull(), "The queue should not be full after deletion.");
+ }
+
+ @Test
+ void testHeapSort() {
+ MinPriorityQueue queue = new MinPriorityQueue(5);
+ queue.insert(10);
+ queue.insert(5);
+ queue.insert(15);
+ queue.insert(1);
+ queue.insert(3);
+
+ // Delete all elements to sort the queue
+ int[] sortedArray = new int[5];
+ for (int i = 0; i < 5; i++) {
+ sortedArray[i] = queue.delete();
+ }
+
+ Assertions.assertArrayEquals(new int[] {1, 3, 5, 10, 15}, sortedArray, "The array should be sorted in ascending order.");
+ }
+
+ @Test
+ void testPeekEmptyQueue() {
+ MinPriorityQueue queue = new MinPriorityQueue(5);
+ Assertions.assertThrows(IllegalStateException.class, queue::peek, "Should throw an exception when peeking into an empty queue.");
+ }
+
+ @Test
+ void testDeleteEmptyQueue() {
+ MinPriorityQueue queue = new MinPriorityQueue(5);
+ Assertions.assertThrows(IllegalStateException.class, queue::delete, "Should throw an exception when deleting from an empty queue.");
+ }
+
+ @Test
+ void testInsertWhenFull() {
+ MinPriorityQueue queue = new MinPriorityQueue(2);
+ queue.insert(10);
+ queue.insert(5);
+
+ Assertions.assertThrows(IllegalStateException.class, () -> queue.insert(15), "Should throw an exception when inserting into a full queue.");
+ }
+}