Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Enhance docs, add tests in GenericHeap #5980

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,90 @@
import java.util.ArrayList;
import java.util.HashMap;

/**
* A generic implementation of a max heap data structure.
*
* @param <T> the type of elements in this heap, must extend Comparable.
*/
public class GenericHeap<T extends Comparable<T>> {

ArrayList<T> data = new ArrayList<>();
HashMap<T, Integer> map = new HashMap<>();
private final ArrayList<T> data = new ArrayList<>();
private final HashMap<T, Integer> 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) {
if (item == null) {
throw new IllegalArgumentException("Cannot insert null into the heap.");
}

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;
Expand All @@ -62,15 +103,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);
Expand All @@ -80,9 +141,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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,114 +13,81 @@ public class GenericHeapTest {
private GenericHeap<Integer> heap;

@BeforeEach
public void setUp() {
void setUp() {
heap = new GenericHeap<>();
}

@Test
public void testGenericHeapAddAndGet() {
heap.add(19);
heap.add(36);
heap.add(100);
heap.add(-17);
heap.add(3);

// Check that the largest element (100) is at the top of the heap
assertEquals(100, heap.get());
}

@Test
public void testGenericHeapRemove() {
heap.add(19);
heap.add(36);
heap.add(100);
heap.add(-17);
heap.add(3);

// Verify that the largest element is removed correctly
assertEquals(100, heap.remove());

// The new element at the top should be 36
assertEquals(36, heap.get());
void testAddAndGet() {
heap.add(10);
heap.add(20);
heap.add(5);

// Check that the size is correct after removal
assertEquals(4, heap.size());
assertEquals(20, heap.get());
}

@Test
public void testGenericHeapSize() {
assertTrue(heap.isEmpty());

void testRemove() {
heap.add(10);
heap.add(20);
heap.add(5);

// Check that the size is correct
assertEquals(2, heap.size());

heap.remove();

// After removal, the size should be 1
assertEquals(1, heap.size());
assertEquals(20, heap.remove());
assertEquals(10, heap.get());
}

@Test
public void testGenericHeapIsEmpty() {
// Verify that the heap is initially empty
void testIsEmpty() {
assertTrue(heap.isEmpty());

heap.add(15);

// Now the heap should not be empty
heap.add(1);
assertFalse(heap.isEmpty());

heap.remove();

// After removing the one element, it should be empty again
assertTrue(heap.isEmpty());
}

@Test
public void testGenericHeapUpdatePriority() {
heap.add(19);
heap.add(36);
heap.add(100);
heap.add(-17);
heap.add(3);

// Verify that the largest element initially is 100
assertEquals(100, heap.get());
void testSize() {
assertEquals(0, heap.size());
heap.add(1);
heap.add(2);
assertEquals(2, heap.size());
}

heap.remove();
@Test
void testUpdatePriority() {
heap.add(10);
heap.add(20);
heap.add(5);

// Simulates a change in priority by increasing the value of 100 to 44
heap.add(44);
heap.updatePriority(10);
assertEquals(20, heap.get());

// Now, the new high should be 25
assertEquals(44, heap.get());
heap.add(30);
heap.updatePriority(20); // 20 will be moved up
assertEquals(30, heap.get());
}

@Test
public void testGenericHeapRemoveUntilEmpty() {
heap.add(5);
heap.add(3);
heap.add(4);
heap.add(1);
heap.add(2);
void testRemoveFromEmptyHeap() {
Exception exception = assertThrows(IllegalStateException.class, () -> heap.remove());
assertEquals("Heap is empty", exception.getMessage());
}

// Remove all items and check that they are removed in descending order
assertEquals(5, heap.remove());
assertEquals(4, heap.remove());
assertEquals(3, heap.remove());
assertEquals(2, heap.remove());
assertEquals(1, heap.remove());
@Test
void testGetFromEmptyHeap() {
Exception exception = assertThrows(IllegalStateException.class, () -> heap.get());
assertEquals("Heap is empty", exception.getMessage());
}

// Empty heap
assertTrue(heap.isEmpty());
@Test
void testUpdatePriorityForNonExistentItem() {
Exception exception = assertThrows(IllegalArgumentException.class, () -> heap.updatePriority(100));
assertEquals("Item not found in the heap", exception.getMessage());
}

@Test
public void testGenericHeapAddNullItem() {
// Check null item
assertThrows(IllegalArgumentException.class, () -> { heap.add(null); });
void testDisplay() {
heap.add(10);
heap.add(20);
heap.add(5);
heap.display(); // Just checking no exceptions are thrown.
}
}