From 6fc2fd99febe5f28a574deaa96f1afb5c81943a4 Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Thu, 24 Oct 2024 12:03:18 +0530 Subject: [PATCH 1/3] refactor: Enhance docs, add tests in `GenericHeap` --- .../datastructures/heaps/GenericHeap.java | 84 +++++++++++++++-- .../datastructures/heaps/GenericHeapTest.java | 93 +++++++++++++++++++ 2 files changed, 169 insertions(+), 8 deletions(-) create mode 100644 src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java diff --git a/src/main/java/com/thealgorithms/datastructures/heaps/GenericHeap.java b/src/main/java/com/thealgorithms/datastructures/heaps/GenericHeap.java index d546b7cc88d4..735e47da1cc8 100644 --- a/src/main/java/com/thealgorithms/datastructures/heaps/GenericHeap.java +++ b/src/main/java/com/thealgorithms/datastructures/heaps/GenericHeap.java @@ -3,45 +3,86 @@ import java.util.ArrayList; import java.util.HashMap; +/** + * A generic implementation of a max heap data structure. + * + * @param the type of elements in this heap, must extend Comparable. + */ public class GenericHeap> { - ArrayList data = new ArrayList<>(); - HashMap map = new HashMap<>(); + private final ArrayList data = new ArrayList<>(); + private final HashMap map = new HashMap<>(); + /** + * Adds an item to the heap, maintaining the heap property. + * + * @param item the item to be added + */ public void add(T item) { this.data.add(item); - map.put(item, this.data.size() - 1); // + map.put(item, this.data.size() - 1); upHeapify(this.data.size() - 1); } + /** + * Restores the heap property by moving the item at the given index upwards. + * + * @param ci the index of the current item + */ private void upHeapify(int ci) { int pi = (ci - 1) / 2; - if (isLarger(this.data.get(ci), this.data.get(pi)) > 0) { + if (ci > 0 && isLarger(this.data.get(ci), this.data.get(pi)) > 0) { swap(pi, ci); upHeapify(pi); } } + /** + * Displays the contents of the heap. + */ public void display() { System.out.println(this.data); } + /** + * Returns the number of elements in the heap. + * + * @return the size of the heap + */ public int size() { return this.data.size(); } + /** + * Checks if the heap is empty. + * + * @return true if the heap is empty, false otherwise + */ public boolean isEmpty() { return this.size() == 0; } + /** + * Removes and returns the maximum item from the heap. + * + * @return the maximum item + */ public T remove() { + if (isEmpty()) { + throw new IllegalStateException("Heap is empty"); + } this.swap(0, this.size() - 1); T rv = this.data.remove(this.size() - 1); - downHeapify(0); map.remove(rv); + downHeapify(0); return rv; } + /** + * Restores the heap property by moving the item at the given index downwards. + * + * @param pi the index of the current item + */ private void downHeapify(int pi) { int lci = 2 * pi + 1; int rci = 2 * pi + 2; @@ -58,15 +99,35 @@ private void downHeapify(int pi) { } } + /** + * Retrieves the maximum item from the heap without removing it. + * + * @return the maximum item + */ public T get() { - return this.data.get(0); + if (isEmpty()) { + throw new IllegalStateException("Heap is empty"); + } + return this.data.getFirst(); } - // t has higher property then return +ve + /** + * Compares two items to determine their order. + * + * @param t the first item + * @param o the second item + * @return a positive integer if t is greater than o, negative if t is less, and zero if they are equal + */ private int isLarger(T t, T o) { return t.compareTo(o); } + /** + * Swaps two items in the heap and updates their indices in the map. + * + * @param i index of the first item + * @param j index of the second item + */ private void swap(int i, int j) { T ith = this.data.get(i); T jth = this.data.get(j); @@ -76,9 +137,16 @@ private void swap(int i, int j) { map.put(jth, i); } + /** + * Updates the priority of the specified item by restoring the heap property. + * + * @param item the item whose priority is to be updated + */ public void updatePriority(T item) { + if (!map.containsKey(item)) { + throw new IllegalArgumentException("Item not found in the heap"); + } int index = map.get(item); - // because we enter lesser value then old vale upHeapify(index); } } diff --git a/src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java b/src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java new file mode 100644 index 000000000000..0f5ee71441cb --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java @@ -0,0 +1,93 @@ +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 org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class GenericHeapTest { + + private GenericHeap heap; + + @BeforeEach + void setUp() { + heap = new GenericHeap<>(); + } + + @Test + void testAddAndGet() { + heap.add(10); + heap.add(20); + heap.add(5); + + assertEquals(20, heap.get()); + } + + @Test + void testRemove() { + heap.add(10); + heap.add(20); + heap.add(5); + + assertEquals(20, heap.remove()); + assertEquals(10, heap.get()); + } + + @Test + void testIsEmpty() { + assertTrue(heap.isEmpty()); + heap.add(1); + assertFalse(heap.isEmpty()); + } + + @Test + void testSize() { + assertEquals(0, heap.size()); + heap.add(1); + heap.add(2); + assertEquals(2, heap.size()); + } + + @Test + void testUpdatePriority() { + heap.add(10); + heap.add(20); + heap.add(5); + + heap.updatePriority(10); // This is a no-op since 10 is not greater than 20. + assertEquals(20, heap.get()); + + heap.add(30); + heap.updatePriority(20); // 20 will be moved up + assertEquals(30, heap.get()); + } + + @Test + void testRemoveFromEmptyHeap() { + Exception exception = assertThrows(IllegalStateException.class, () -> heap.remove()); + assertEquals("Heap is empty", exception.getMessage()); + } + + @Test + void testGetFromEmptyHeap() { + Exception exception = assertThrows(IllegalStateException.class, () -> heap.get()); + assertEquals("Heap is empty", exception.getMessage()); + } + + @Test + void testUpdatePriorityForNonExistentItem() { + Exception exception = assertThrows(IllegalArgumentException.class, () -> heap.updatePriority(100)); + assertEquals("Item not found in the heap", exception.getMessage()); + } + + @Test + void testDisplay() { + heap.add(10); + heap.add(20); + heap.add(5); + heap.display(); // Just checking no exceptions are thrown. + } +} From 66c834ba24c47948642ab9e253ce5f1cbdbd683c Mon Sep 17 00:00:00 2001 From: Hardvan Date: Thu, 24 Oct 2024 06:33:37 +0000 Subject: [PATCH 2/3] Update directory --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 1def3e25c064..5bf389600f71 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -826,6 +826,7 @@ * [HashMapCuckooHashingTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/hashmap/HashMapCuckooHashingTest.java) * heaps * [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) * lists * [CircleLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CircleLinkedListTest.java) From 572b8c23b9524eb23dd1e9be5747036f0126706c Mon Sep 17 00:00:00 2001 From: Hardik Pawar Date: Thu, 24 Oct 2024 12:10:03 +0530 Subject: [PATCH 3/3] Fix --- .../com/thealgorithms/datastructures/heaps/GenericHeapTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java b/src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java index 0f5ee71441cb..60b9787a16fb 100644 --- a/src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java +++ b/src/test/java/com/thealgorithms/datastructures/heaps/GenericHeapTest.java @@ -57,7 +57,7 @@ void testUpdatePriority() { heap.add(20); heap.add(5); - heap.updatePriority(10); // This is a no-op since 10 is not greater than 20. + heap.updatePriority(10); assertEquals(20, heap.get()); heap.add(30);