From 91234747294a788a8f7cd6a918f24e7df74832f2 Mon Sep 17 00:00:00 2001 From: adrianparas <97486758+adrianparas@users.noreply.github.com> Date: Thu, 29 Dec 2022 07:19:35 -0500 Subject: [PATCH] Add Leftist Heap (#3789) Co-authored-by: Adrian Paras --- .../datastructures/heaps/LeftistHeap.java | 118 ++++++++++++++++++ .../datastructures/heaps/LeftistHeapTest.java | 28 +++++ 2 files changed, 146 insertions(+) create mode 100644 src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java create mode 100644 src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java diff --git a/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java b/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java new file mode 100644 index 000000000..66861ac1d --- /dev/null +++ b/src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java @@ -0,0 +1,118 @@ +package com.thealgorithms.datastructures.heaps; + +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. + * + * Source: https://iq.opengenus.org/leftist-heap/ + * + */ + +public class LeftistHeap { + private class Node { + private int element, npl; + private Node left, right; + + // Node constructor setting the data element and left/right pointers to null + private Node(int element) { + this.element = element; + left = right = null; + npl = 0; + } + } + + private Node root; + + // Constructor + public LeftistHeap() { + root = null; + } + + // Checks if heap is empty + public boolean isEmpty() { + return root == null; + } + + // Resets structure to initial state + public void clear() { + // We will put head is null + root = null; + } + + // Merge function that merges the contents of another leftist heap with the + // current one + public void merge(LeftistHeap h1) { + // If the present function is rhs then we ignore the merge + root = merge(root, h1.root); + h1.root = null; + } + + // Function merge with two Nodes a and b + public Node merge(Node a, Node b) { + if (a == null) + return b; + + if (b == null) + return a; + + // Violates leftist property, so must do a swap + if (a.element > b.element) { + Node temp = a; + a = b; + b = temp; + } + + // Now we call the function merge to merge a and b + a.right = merge(a.right, b); + + // Violates leftist property so must swap here + if (a.left == null) { + a.left = a.right; + a.right = null; + } else { + if (a.left.npl < a.right.npl) { + Node temp = a.left; + a.left = a.right; + a.right = temp; + } + a.npl = a.right.npl + 1; + } + return a; + } + + // Function insert. Uses the merge function to add the data + public void insert(int a) { + root = merge(new Node(a), root); + } + + // Returns and removes the minimum element in the heap + public int extract_min() { + // If is empty return -1 + if (isEmpty()) + return -1; + + int min = root.element; + root = merge(root.left, root.right); + return min; + } + + // Function returning a list of an in order traversal of the data structure + public ArrayList in_order() { + ArrayList lst = new ArrayList<>(); + in_order_aux(root, lst); + return new ArrayList<>(lst); + } + + // Auxiliary function for in_order + private void in_order_aux(Node n, ArrayList lst) { + if (n == null) + return; + in_order_aux(n.left, lst); + lst.add(n.element); + in_order_aux(n.right, lst); + } +} \ No newline at end of file diff --git a/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java b/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java new file mode 100644 index 000000000..b0cb0d196 --- /dev/null +++ b/src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java @@ -0,0 +1,28 @@ +package com.thealgorithms.datastructures.heaps; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class LeftistHeapTest { + + @Test + void testLeftistHeap() { + 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.in_order(); + Assertions.assertTrue(heap.in_order().toString().equals("[6, 2, 3, 1]")); + Assertions.assertTrue(heap.extract_min() == 1); + Assertions.assertTrue(heap.in_order().toString().equals("[6, 2, 3]")); + heap.insert(8); + heap.insert(12); + heap.insert(4); + Assertions.assertTrue(heap.in_order().toString().equals("[8, 3, 12, 2, 6, 4]")); + heap.clear(); + Assertions.assertTrue(heap.isEmpty()); + } +} \ No newline at end of file