mirror of
https://github.com/TheAlgorithms/Java.git
synced 2025-07-06 17:29:31 +08:00
Enhance docs, add tests in MinHeap (#5985)
This commit is contained in:
@ -871,6 +871,7 @@
|
|||||||
* [LeftistHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java)
|
* [LeftistHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java)
|
||||||
* [MedianFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java)
|
* [MedianFinderTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MedianFinderTest.java)
|
||||||
* [MergeKSortedArraysTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MergeKSortedArraysTest.java)
|
* [MergeKSortedArraysTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MergeKSortedArraysTest.java)
|
||||||
|
* [MinHeapTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MinHeapTest.java)
|
||||||
* [MinPriorityQueueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MinPriorityQueueTest.java)
|
* [MinPriorityQueueTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/heaps/MinPriorityQueueTest.java)
|
||||||
* lists
|
* lists
|
||||||
* [CircleLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CircleLinkedListTest.java)
|
* [CircleLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CircleLinkedListTest.java)
|
||||||
|
@ -40,5 +40,5 @@ public interface Heap {
|
|||||||
* @param elementIndex int containing the position in the heap of the
|
* @param elementIndex int containing the position in the heap of the
|
||||||
* element to be deleted.
|
* element to be deleted.
|
||||||
*/
|
*/
|
||||||
void deleteElement(int elementIndex);
|
void deleteElement(int elementIndex) throws EmptyHeapException;
|
||||||
}
|
}
|
||||||
|
@ -167,4 +167,8 @@ public class HeapElement {
|
|||||||
result += (additionalInfo != null) ? additionalInfo.hashCode() : 0;
|
result += (additionalInfo != null) ? additionalInfo.hashCode() : 0;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return additionalInfo.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,25 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Heap tree where a node's key is higher than or equal to its parent's and
|
* A Min Heap implementation where each node's key is lower than or equal to its children's keys.
|
||||||
* lower than or equal to its children's.
|
* This data structure provides O(log n) time complexity for insertion and deletion operations,
|
||||||
|
* and O(1) for retrieving the minimum element.
|
||||||
|
*
|
||||||
|
* Properties:
|
||||||
|
* 1. Complete Binary Tree
|
||||||
|
* 2. Parent node's key ≤ Children nodes' keys
|
||||||
|
* 3. Root contains the minimum element
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
* ```java
|
||||||
|
* List<HeapElement> elements = Arrays.asList(
|
||||||
|
* new HeapElement(5, "Five"),
|
||||||
|
* new HeapElement(2, "Two")
|
||||||
|
* );
|
||||||
|
* MinHeap heap = new MinHeap(elements);
|
||||||
|
* heap.insertElement(new HeapElement(1, "One"));
|
||||||
|
* HeapElement min = heap.getElement(); // Returns and removes the minimum element
|
||||||
|
* ```
|
||||||
*
|
*
|
||||||
* @author Nicolas Renard
|
* @author Nicolas Renard
|
||||||
*/
|
*/
|
||||||
@ -13,113 +30,242 @@ public class MinHeap implements Heap {
|
|||||||
|
|
||||||
private final List<HeapElement> minHeap;
|
private final List<HeapElement> minHeap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new MinHeap from a list of elements.
|
||||||
|
* Null elements in the input list are ignored with a warning message.
|
||||||
|
*
|
||||||
|
* @param listElements List of HeapElement objects to initialize the heap
|
||||||
|
* @throws IllegalArgumentException if the input list is null
|
||||||
|
*/
|
||||||
public MinHeap(List<HeapElement> listElements) {
|
public MinHeap(List<HeapElement> listElements) {
|
||||||
|
if (listElements == null) {
|
||||||
|
throw new IllegalArgumentException("Input list cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
minHeap = new ArrayList<>();
|
minHeap = new ArrayList<>();
|
||||||
|
|
||||||
|
// Safe initialization: directly add elements first
|
||||||
for (HeapElement heapElement : listElements) {
|
for (HeapElement heapElement : listElements) {
|
||||||
if (heapElement != null) {
|
if (heapElement != null) {
|
||||||
insertElement(heapElement);
|
minHeap.add(heapElement);
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Null element. Not added to heap");
|
System.out.println("Null element. Not added to heap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Heapify the array bottom-up
|
||||||
|
for (int i = minHeap.size() / 2; i >= 0; i--) {
|
||||||
|
heapifyDown(i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (minHeap.isEmpty()) {
|
if (minHeap.isEmpty()) {
|
||||||
System.out.println("No element has been added, empty heap.");
|
System.out.println("No element has been added, empty heap.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the element at a given index. The key for the list is equal to index value - 1
|
/**
|
||||||
|
* Retrieves the element at the specified index without removing it.
|
||||||
|
* Note: The index is 1-based for consistency with heap operations.
|
||||||
|
*
|
||||||
|
* @param elementIndex 1-based index of the element to retrieve
|
||||||
|
* @return HeapElement at the specified index
|
||||||
|
* @throws IndexOutOfBoundsException if the index is invalid
|
||||||
|
*/
|
||||||
public HeapElement getElement(int elementIndex) {
|
public HeapElement getElement(int elementIndex) {
|
||||||
if ((elementIndex <= 0) || (elementIndex > minHeap.size())) {
|
if ((elementIndex <= 0) || (elementIndex > minHeap.size())) {
|
||||||
throw new IndexOutOfBoundsException("Index out of heap range");
|
throw new IndexOutOfBoundsException("Index " + elementIndex + " is out of heap range [1, " + minHeap.size() + "]");
|
||||||
}
|
}
|
||||||
return minHeap.get(elementIndex - 1);
|
return minHeap.get(elementIndex - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the key of the element at a given index
|
/**
|
||||||
|
* Retrieves the key value of an element at the specified index.
|
||||||
|
*
|
||||||
|
* @param elementIndex 1-based index of the element
|
||||||
|
* @return double value representing the key
|
||||||
|
* @throws IndexOutOfBoundsException if the index is invalid
|
||||||
|
*/
|
||||||
private double getElementKey(int elementIndex) {
|
private double getElementKey(int elementIndex) {
|
||||||
if ((elementIndex <= 0) || (elementIndex > minHeap.size())) {
|
if ((elementIndex <= 0) || (elementIndex > minHeap.size())) {
|
||||||
throw new IndexOutOfBoundsException("Index out of heap range");
|
throw new IndexOutOfBoundsException("Index " + elementIndex + " is out of heap range [1, " + minHeap.size() + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
return minHeap.get(elementIndex - 1).getKey();
|
return minHeap.get(elementIndex - 1).getKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swaps two elements in the heap
|
/**
|
||||||
|
* Swaps two elements in the heap.
|
||||||
|
*
|
||||||
|
* @param index1 1-based index of first element
|
||||||
|
* @param index2 1-based index of second element
|
||||||
|
*/
|
||||||
private void swap(int index1, int index2) {
|
private void swap(int index1, int index2) {
|
||||||
HeapElement temporaryElement = minHeap.get(index1 - 1);
|
HeapElement temporaryElement = minHeap.get(index1 - 1);
|
||||||
minHeap.set(index1 - 1, minHeap.get(index2 - 1));
|
minHeap.set(index1 - 1, minHeap.get(index2 - 1));
|
||||||
minHeap.set(index2 - 1, temporaryElement);
|
minHeap.set(index2 - 1, temporaryElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle an element up to its right place as long as its key is lower than its parent's
|
/**
|
||||||
private void toggleUp(int elementIndex) {
|
* Maintains heap properties by moving an element down the heap.
|
||||||
double key = minHeap.get(elementIndex - 1).getKey();
|
* Used specifically during initialization.
|
||||||
while (getElementKey((int) Math.floor(elementIndex / 2.0) + 1) > key) {
|
*
|
||||||
swap(elementIndex, (int) Math.floor(elementIndex / 2.0));
|
* @param elementIndex 1-based index of the element to heapify
|
||||||
elementIndex = (int) Math.floor(elementIndex / 2.0);
|
*/
|
||||||
|
private void heapifyDown(int elementIndex) {
|
||||||
|
int smallest = elementIndex - 1; // Convert to 0-based index
|
||||||
|
int leftChild = 2 * elementIndex - 1;
|
||||||
|
int rightChild = 2 * elementIndex;
|
||||||
|
|
||||||
|
// Check if left child is smaller than root
|
||||||
|
if (leftChild < minHeap.size() && minHeap.get(leftChild).getKey() < minHeap.get(smallest).getKey()) {
|
||||||
|
smallest = leftChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if right child is smaller than smallest so far
|
||||||
|
if (rightChild < minHeap.size() && minHeap.get(rightChild).getKey() < minHeap.get(smallest).getKey()) {
|
||||||
|
smallest = rightChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If smallest is not root
|
||||||
|
if (smallest != elementIndex - 1) {
|
||||||
|
HeapElement swap = minHeap.get(elementIndex - 1);
|
||||||
|
minHeap.set(elementIndex - 1, minHeap.get(smallest));
|
||||||
|
minHeap.set(smallest, swap);
|
||||||
|
|
||||||
|
// Recursively heapify the affected sub-tree
|
||||||
|
heapifyDown(smallest + 1); // Convert back to 1-based index
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggle an element down to its right place as long as its key is higher
|
/**
|
||||||
// than any of its children's
|
* Moves an element up the heap until heap properties are satisfied.
|
||||||
|
* This operation is called after insertion to maintain heap properties.
|
||||||
|
*
|
||||||
|
* @param elementIndex 1-based index of the element to move up
|
||||||
|
*/
|
||||||
|
private void toggleUp(int elementIndex) {
|
||||||
|
if (elementIndex <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double key = minHeap.get(elementIndex - 1).getKey();
|
||||||
|
int parentIndex = (int) Math.floor(elementIndex / 2.0);
|
||||||
|
|
||||||
|
while (elementIndex > 1 && getElementKey(parentIndex) > key) {
|
||||||
|
swap(elementIndex, parentIndex);
|
||||||
|
elementIndex = parentIndex;
|
||||||
|
parentIndex = (int) Math.floor(elementIndex / 2.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves an element down the heap until heap properties are satisfied.
|
||||||
|
* This operation is called after deletion to maintain heap properties.
|
||||||
|
*
|
||||||
|
* @param elementIndex 1-based index of the element to move down
|
||||||
|
*/
|
||||||
private void toggleDown(int elementIndex) {
|
private void toggleDown(int elementIndex) {
|
||||||
double key = minHeap.get(elementIndex - 1).getKey();
|
double key = minHeap.get(elementIndex - 1).getKey();
|
||||||
boolean wrongOrder = (key > getElementKey(elementIndex * 2)) || (key > getElementKey(Math.min(elementIndex * 2, minHeap.size())));
|
int size = minHeap.size();
|
||||||
while ((2 * elementIndex <= minHeap.size()) && wrongOrder) {
|
|
||||||
// Check whether it shall swap the element with its left child or its right one if any.
|
while (true) {
|
||||||
if ((2 * elementIndex < minHeap.size()) && (getElementKey(elementIndex * 2 + 1) < getElementKey(elementIndex * 2))) {
|
int smallest = elementIndex;
|
||||||
swap(elementIndex, 2 * elementIndex + 1);
|
int leftChild = 2 * elementIndex;
|
||||||
elementIndex = 2 * elementIndex + 1;
|
int rightChild = 2 * elementIndex + 1;
|
||||||
} else {
|
|
||||||
swap(elementIndex, 2 * elementIndex);
|
if (leftChild <= size && getElementKey(leftChild) < key) {
|
||||||
elementIndex = 2 * elementIndex;
|
smallest = leftChild;
|
||||||
}
|
}
|
||||||
wrongOrder = (key > getElementKey(elementIndex * 2)) || (key > getElementKey(Math.min(elementIndex * 2, minHeap.size())));
|
|
||||||
|
if (rightChild <= size && getElementKey(rightChild) < getElementKey(smallest)) {
|
||||||
|
smallest = rightChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (smallest == elementIndex) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(elementIndex, smallest);
|
||||||
|
elementIndex = smallest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HeapElement extractMin() {
|
/**
|
||||||
HeapElement result = minHeap.get(0);
|
* Extracts and returns the minimum element from the heap.
|
||||||
deleteElement(0);
|
*
|
||||||
|
* @return HeapElement with the lowest key
|
||||||
|
* @throws EmptyHeapException if the heap is empty
|
||||||
|
*/
|
||||||
|
private HeapElement extractMin() throws EmptyHeapException {
|
||||||
|
if (minHeap.isEmpty()) {
|
||||||
|
throw new EmptyHeapException("Cannot extract from empty heap");
|
||||||
|
}
|
||||||
|
HeapElement result = minHeap.getFirst();
|
||||||
|
deleteElement(1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public final void insertElement(HeapElement element) {
|
public void insertElement(HeapElement element) {
|
||||||
|
if (element == null) {
|
||||||
|
throw new IllegalArgumentException("Cannot insert null element");
|
||||||
|
}
|
||||||
minHeap.add(element);
|
minHeap.add(element);
|
||||||
toggleUp(minHeap.size());
|
toggleUp(minHeap.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void deleteElement(int elementIndex) {
|
public void deleteElement(int elementIndex) throws EmptyHeapException {
|
||||||
if (minHeap.isEmpty()) {
|
if (minHeap.isEmpty()) {
|
||||||
try {
|
throw new EmptyHeapException("Cannot delete from empty heap");
|
||||||
throw new EmptyHeapException("Attempt to delete an element from an empty heap");
|
|
||||||
} catch (EmptyHeapException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if ((elementIndex > minHeap.size()) || (elementIndex <= 0)) {
|
if ((elementIndex > minHeap.size()) || (elementIndex <= 0)) {
|
||||||
throw new IndexOutOfBoundsException("Index out of heap range");
|
throw new IndexOutOfBoundsException("Index " + elementIndex + " is out of heap range [1, " + minHeap.size() + "]");
|
||||||
}
|
}
|
||||||
// The last element in heap replaces the one to be deleted
|
|
||||||
minHeap.set(elementIndex - 1, getElement(minHeap.size()));
|
// Replace with last element and remove last position
|
||||||
minHeap.remove(minHeap.size());
|
minHeap.set(elementIndex - 1, minHeap.getLast());
|
||||||
// Shall the new element be moved up...
|
minHeap.removeLast();
|
||||||
if (getElementKey(elementIndex) < getElementKey((int) Math.floor(elementIndex / 2.0))) {
|
|
||||||
|
// No need to toggle if we just removed the last element
|
||||||
|
if (!minHeap.isEmpty() && elementIndex <= minHeap.size()) {
|
||||||
|
// Determine whether to toggle up or down
|
||||||
|
if (elementIndex > 1 && getElementKey(elementIndex) < getElementKey((int) Math.floor(elementIndex / 2.0))) {
|
||||||
toggleUp(elementIndex);
|
toggleUp(elementIndex);
|
||||||
} // ... or down ?
|
} else {
|
||||||
else if (((2 * elementIndex <= minHeap.size()) && (getElementKey(elementIndex) > getElementKey(elementIndex * 2))) || ((2 * elementIndex < minHeap.size()) && (getElementKey(elementIndex) > getElementKey(elementIndex * 2)))) {
|
|
||||||
toggleDown(elementIndex);
|
toggleDown(elementIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public HeapElement getElement() throws EmptyHeapException {
|
public HeapElement getElement() throws EmptyHeapException {
|
||||||
try {
|
|
||||||
return extractMin();
|
return extractMin();
|
||||||
} catch (Exception e) {
|
|
||||||
throw new EmptyHeapException("Heap is empty. Error retrieving element", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current size of the heap.
|
||||||
|
*
|
||||||
|
* @return number of elements in the heap
|
||||||
|
*/
|
||||||
|
public int size() {
|
||||||
|
return minHeap.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the heap is empty.
|
||||||
|
*
|
||||||
|
* @return true if the heap contains no elements
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return minHeap.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,141 @@
|
|||||||
|
package com.thealgorithms.datastructures.heaps;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class MinHeapTest {
|
||||||
|
|
||||||
|
private MinHeap heap;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
// Create a fresh heap for each test
|
||||||
|
List<HeapElement> elements = Arrays.asList(new HeapElement(5.0, "Five"), new HeapElement(2.0, "Two"), new HeapElement(8.0, "Eight"), new HeapElement(1.0, "One"), new HeapElement(9.0, "Nine"));
|
||||||
|
heap = new MinHeap(elements);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructorWithNullList() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> new MinHeap(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructorWithEmptyList() {
|
||||||
|
MinHeap emptyHeap = new MinHeap(new ArrayList<>());
|
||||||
|
assertTrue(emptyHeap.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testConstructorWithNullElements() {
|
||||||
|
List<HeapElement> elements = Arrays.asList(new HeapElement(1.0, "One"), null, new HeapElement(2.0, "Two"));
|
||||||
|
MinHeap heap = new MinHeap(elements);
|
||||||
|
assertEquals(2, heap.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsertElement() {
|
||||||
|
heap.insertElement(new HeapElement(0.5, "Half"));
|
||||||
|
assertEquals(0.5, heap.getElement(1).getKey());
|
||||||
|
assertEquals(6, heap.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsertNullElement() {
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> heap.insertElement(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetElementAtIndex() {
|
||||||
|
HeapElement element = heap.getElement(1);
|
||||||
|
assertEquals(1.0, element.getKey());
|
||||||
|
assertEquals("One", element.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetElementAtInvalidIndex() {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> heap.getElement(0));
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> heap.getElement(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteElement() throws EmptyHeapException {
|
||||||
|
heap.deleteElement(1);
|
||||||
|
assertEquals(2.0, heap.getElement(1).getKey());
|
||||||
|
assertEquals(4, heap.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteElementAtInvalidIndex() {
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> heap.deleteElement(0));
|
||||||
|
assertThrows(IndexOutOfBoundsException.class, () -> heap.deleteElement(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteFromEmptyHeap() {
|
||||||
|
MinHeap emptyHeap = new MinHeap(new ArrayList<>());
|
||||||
|
assertThrows(EmptyHeapException.class, () -> emptyHeap.deleteElement(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExtractMin() throws EmptyHeapException {
|
||||||
|
HeapElement min = heap.getElement();
|
||||||
|
assertEquals(1.0, min.getKey());
|
||||||
|
assertEquals("One", min.getValue());
|
||||||
|
assertEquals(4, heap.size());
|
||||||
|
|
||||||
|
min = heap.getElement();
|
||||||
|
assertEquals(2.0, min.getKey());
|
||||||
|
assertEquals(3, heap.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExtractMinFromEmptyHeap() {
|
||||||
|
MinHeap emptyHeap = new MinHeap(new ArrayList<>());
|
||||||
|
assertThrows(EmptyHeapException.class, () -> emptyHeap.getElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testHeapOrder() {
|
||||||
|
// Test that parent is always smaller than or equal to children
|
||||||
|
for (int i = 1; i <= heap.size() / 2; i++) {
|
||||||
|
double parentKey = heap.getElement(i).getKey();
|
||||||
|
|
||||||
|
// Check left child
|
||||||
|
if (2 * i <= heap.size()) {
|
||||||
|
assertTrue(parentKey <= heap.getElement(2 * i).getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check right child
|
||||||
|
if (2 * i + 1 <= heap.size()) {
|
||||||
|
assertTrue(parentKey <= heap.getElement(2 * i + 1).getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSizeAndEmpty() {
|
||||||
|
assertEquals(5, heap.size());
|
||||||
|
assertFalse(heap.isEmpty());
|
||||||
|
|
||||||
|
// Remove all elements
|
||||||
|
while (!heap.isEmpty()) {
|
||||||
|
try {
|
||||||
|
heap.getElement();
|
||||||
|
} catch (EmptyHeapException e) {
|
||||||
|
Assertions.fail("Should not throw EmptyHeapException while heap is not empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(0, heap.size());
|
||||||
|
assertTrue(heap.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user