diff --git a/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java b/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java index ca18673c6724..1c91d24f0fb5 100644 --- a/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java +++ b/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java @@ -2,24 +2,33 @@ import java.util.ArrayList; -/* - * This is a leftist heap that follows the same operations as a - * binary min heap, but may be unbalanced at times and follows a - * leftist property, in which the left side is more heavy on the - * right based on the null-path length (npl) values. +/** + * This class implements a Leftist Heap, which is a type of priority queue + * that follows similar operations to a binary min-heap but allows for + * unbalanced structures based on the leftist property. * - * Source: https://iq.opengenus.org/leftist-heap/ + *

+ * A Leftist Heap maintains the leftist property, which ensures that the + * left subtree is heavier than the right subtree based on the + * null-path length (npl) values. This allows for efficient merging + * of heaps and supports operations like insertion, extraction of + * the minimum element, and in-order traversal. + *

* + *

+ * For more information on Leftist Heaps, visit: + * OpenGenus + *

*/ - public class LeftistHeap { + // Node class representing each element in the Leftist Heap private static final class Node { private final int element; private int npl; private Node left; private Node right; - // Node constructor setting the data element and left/right pointers to null + // Node constructor that initializes the element and sets child pointers to null private Node(int element) { this.element = element; left = null; @@ -30,31 +39,45 @@ private Node(int element) { private Node root; - // Constructor + // Constructor initializing an empty Leftist Heap public LeftistHeap() { root = null; } - // Checks if heap is empty + /** + * Checks if the heap is empty. + * + * @return true if the heap is empty; false otherwise + */ public boolean isEmpty() { return root == null; } - // Resets structure to initial state + /** + * Resets the heap to its initial state, effectively clearing all elements. + */ public void clear() { - // We will put head is null - root = null; + root = null; // Set root to null to clear the heap } - // Merge function that merges the contents of another leftist heap with the - // current one + /** + * Merges the contents of another Leftist Heap into this one. + * + * @param h1 the LeftistHeap to be merged into this heap + */ public void merge(LeftistHeap h1) { - // If the present function is rhs then we ignore the merge + // Merge the current heap with the provided heap and set the provided heap's root to null root = merge(root, h1.root); h1.root = null; } - // Function merge with two Nodes a and b + /** + * Merges two nodes, maintaining the leftist property. + * + * @param a the first node + * @param b the second node + * @return the merged node maintaining the leftist property + */ public Node merge(Node a, Node b) { if (a == null) { return b; @@ -64,17 +87,17 @@ public Node merge(Node a, Node b) { return a; } - // Violates leftist property, so must do a swap + // Ensure that the leftist property is maintained if (a.element > b.element) { Node temp = a; a = b; b = temp; } - // Now we call the function merge to merge a and b + // Merge the right child of node a with node b a.right = merge(a.right, b); - // Violates leftist property so must swap here + // If left child is null, make right child the left child if (a.left == null) { a.left = a.right; a.right = null; @@ -89,14 +112,21 @@ public Node merge(Node a, Node b) { return a; } - // Function insert. Uses the merge function to add the data + /** + * Inserts a new element into the Leftist Heap. + * + * @param a the element to be inserted + */ public void insert(int a) { root = merge(new Node(a), root); } - // Returns and removes the minimum element in the heap + /** + * Extracts and removes the minimum element from the heap. + * + * @return the minimum element in the heap, or -1 if the heap is empty + */ public int extractMin() { - // If is empty return -1 if (isEmpty()) { return -1; } @@ -106,14 +136,23 @@ public int extractMin() { return min; } - // Function returning a list of an in order traversal of the data structure + /** + * Returns a list of the elements in the heap in in-order traversal. + * + * @return an ArrayList containing the elements in in-order + */ public ArrayList inOrder() { ArrayList lst = new ArrayList<>(); inOrderAux(root, lst); return new ArrayList<>(lst); } - // Auxiliary function for in_order + /** + * Auxiliary function for in-order traversal + * + * @param n the current node + * @param lst the list to store the elements in in-order + */ private void inOrderAux(Node n, ArrayList lst) { if (n == null) { return; diff --git a/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java b/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java index f4c4c548ffbf..8c313237f88f 100644 --- a/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java +++ b/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java @@ -6,23 +6,80 @@ public class LeftistHeapTest { @Test - void testLeftistHeap() { + void testIsEmpty() { + LeftistHeap heap = new LeftistHeap(); + Assertions.assertTrue(heap.isEmpty(), "Heap should be empty initially."); + + heap.insert(10); + Assertions.assertFalse(heap.isEmpty(), "Heap should not be empty after insertion."); + + heap.clear(); + Assertions.assertTrue(heap.isEmpty(), "Heap should be empty after clearing."); + } + + @Test + void testInsertAndExtractMin() { LeftistHeap heap = new LeftistHeap(); - Assertions.assertTrue(heap.isEmpty()); heap.insert(6); - Assertions.assertTrue(!heap.isEmpty()); heap.insert(2); heap.insert(3); heap.insert(1); - heap.inOrder(); - Assertions.assertTrue(heap.inOrder().toString().equals("[6, 2, 3, 1]")); - Assertions.assertTrue(heap.extractMin() == 1); - Assertions.assertTrue(heap.inOrder().toString().equals("[6, 2, 3]")); + + Assertions.assertEquals(1, heap.extractMin(), "Minimum should be 1."); + Assertions.assertEquals(2, heap.extractMin(), "Next minimum should be 2."); + Assertions.assertEquals(3, heap.extractMin(), "Next minimum should be 3."); + Assertions.assertEquals(6, heap.extractMin(), "Next minimum should be 6."); + Assertions.assertEquals(-1, heap.extractMin(), "Extracting from an empty heap should return -1."); + } + + @Test + void testMerge() { + LeftistHeap heap1 = new LeftistHeap(); + heap1.insert(1); + heap1.insert(3); + heap1.insert(5); + + LeftistHeap heap2 = new LeftistHeap(); + heap2.insert(2); + heap2.insert(4); + heap2.insert(6); + + heap1.merge(heap2); + + Assertions.assertEquals(1, heap1.extractMin(), "After merging, minimum should be 1."); + Assertions.assertEquals(2, heap1.extractMin(), "Next minimum should be 2."); + Assertions.assertEquals(3, heap1.extractMin(), "Next minimum should be 3."); + Assertions.assertEquals(4, heap1.extractMin(), "Next minimum should be 4."); + Assertions.assertEquals(5, heap1.extractMin(), "Next minimum should be 5."); + Assertions.assertEquals(6, heap1.extractMin(), "Next minimum should be 6."); + Assertions.assertEquals(-1, heap1.extractMin(), "Extracting from an empty heap should return -1."); + } + + @Test + void testInOrderTraversal() { + LeftistHeap heap = new LeftistHeap(); + heap.insert(10); + heap.insert(5); + heap.insert(20); + heap.insert(15); + heap.insert(30); + + Assertions.assertEquals("[20, 15, 30, 5, 10]", heap.inOrder().toString(), "In-order traversal should match the expected output."); + } + + @Test + void testMultipleExtractions() { + LeftistHeap heap = new LeftistHeap(); + heap.insert(10); + heap.insert(5); + heap.insert(3); heap.insert(8); - heap.insert(12); - heap.insert(4); - Assertions.assertTrue(heap.inOrder().toString().equals("[8, 3, 12, 2, 6, 4]")); - heap.clear(); - Assertions.assertTrue(heap.isEmpty()); + + // Extract multiple elements + Assertions.assertEquals(3, heap.extractMin()); + Assertions.assertEquals(5, heap.extractMin()); + Assertions.assertEquals(8, heap.extractMin()); + Assertions.assertEquals(10, heap.extractMin()); + Assertions.assertEquals(-1, heap.extractMin(), "Extracting from an empty heap should return -1."); } }