Skip to content

Commit 20239f2

Browse files
authored
Enhance docs, add tests in LeftistHeap (#5982)
1 parent 709d977 commit 20239f2

File tree

2 files changed

+133
-37
lines changed

2 files changed

+133
-37
lines changed

src/main/java/com/thealgorithms/datastructures/heaps/LeftistHeap.java

Lines changed: 64 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,33 @@
22

33
import java.util.ArrayList;
44

5-
/*
6-
* This is a leftist heap that follows the same operations as a
7-
* binary min heap, but may be unbalanced at times and follows a
8-
* leftist property, in which the left side is more heavy on the
9-
* right based on the null-path length (npl) values.
5+
/**
6+
* This class implements a Leftist Heap, which is a type of priority queue
7+
* that follows similar operations to a binary min-heap but allows for
8+
* unbalanced structures based on the leftist property.
109
*
11-
* Source: https://iq.opengenus.org/leftist-heap/
10+
* <p>
11+
* A Leftist Heap maintains the leftist property, which ensures that the
12+
* left subtree is heavier than the right subtree based on the
13+
* null-path length (npl) values. This allows for efficient merging
14+
* of heaps and supports operations like insertion, extraction of
15+
* the minimum element, and in-order traversal.
16+
* </p>
1217
*
18+
* <p>
19+
* For more information on Leftist Heaps, visit:
20+
* <a href="https://iq.opengenus.org/leftist-heap/">OpenGenus</a>
21+
* </p>
1322
*/
14-
1523
public class LeftistHeap {
24+
// Node class representing each element in the Leftist Heap
1625
private static final class Node {
1726
private final int element;
1827
private int npl;
1928
private Node left;
2029
private Node right;
2130

22-
// Node constructor setting the data element and left/right pointers to null
31+
// Node constructor that initializes the element and sets child pointers to null
2332
private Node(int element) {
2433
this.element = element;
2534
left = null;
@@ -30,31 +39,45 @@ private Node(int element) {
3039

3140
private Node root;
3241

33-
// Constructor
42+
// Constructor initializing an empty Leftist Heap
3443
public LeftistHeap() {
3544
root = null;
3645
}
3746

38-
// Checks if heap is empty
47+
/**
48+
* Checks if the heap is empty.
49+
*
50+
* @return true if the heap is empty; false otherwise
51+
*/
3952
public boolean isEmpty() {
4053
return root == null;
4154
}
4255

43-
// Resets structure to initial state
56+
/**
57+
* Resets the heap to its initial state, effectively clearing all elements.
58+
*/
4459
public void clear() {
45-
// We will put head is null
46-
root = null;
60+
root = null; // Set root to null to clear the heap
4761
}
4862

49-
// Merge function that merges the contents of another leftist heap with the
50-
// current one
63+
/**
64+
* Merges the contents of another Leftist Heap into this one.
65+
*
66+
* @param h1 the LeftistHeap to be merged into this heap
67+
*/
5168
public void merge(LeftistHeap h1) {
52-
// If the present function is rhs then we ignore the merge
69+
// Merge the current heap with the provided heap and set the provided heap's root to null
5370
root = merge(root, h1.root);
5471
h1.root = null;
5572
}
5673

57-
// Function merge with two Nodes a and b
74+
/**
75+
* Merges two nodes, maintaining the leftist property.
76+
*
77+
* @param a the first node
78+
* @param b the second node
79+
* @return the merged node maintaining the leftist property
80+
*/
5881
public Node merge(Node a, Node b) {
5982
if (a == null) {
6083
return b;
@@ -64,17 +87,17 @@ public Node merge(Node a, Node b) {
6487
return a;
6588
}
6689

67-
// Violates leftist property, so must do a swap
90+
// Ensure that the leftist property is maintained
6891
if (a.element > b.element) {
6992
Node temp = a;
7093
a = b;
7194
b = temp;
7295
}
7396

74-
// Now we call the function merge to merge a and b
97+
// Merge the right child of node a with node b
7598
a.right = merge(a.right, b);
7699

77-
// Violates leftist property so must swap here
100+
// If left child is null, make right child the left child
78101
if (a.left == null) {
79102
a.left = a.right;
80103
a.right = null;
@@ -89,14 +112,21 @@ public Node merge(Node a, Node b) {
89112
return a;
90113
}
91114

92-
// Function insert. Uses the merge function to add the data
115+
/**
116+
* Inserts a new element into the Leftist Heap.
117+
*
118+
* @param a the element to be inserted
119+
*/
93120
public void insert(int a) {
94121
root = merge(new Node(a), root);
95122
}
96123

97-
// Returns and removes the minimum element in the heap
124+
/**
125+
* Extracts and removes the minimum element from the heap.
126+
*
127+
* @return the minimum element in the heap, or -1 if the heap is empty
128+
*/
98129
public int extractMin() {
99-
// If is empty return -1
100130
if (isEmpty()) {
101131
return -1;
102132
}
@@ -106,14 +136,23 @@ public int extractMin() {
106136
return min;
107137
}
108138

109-
// Function returning a list of an in order traversal of the data structure
139+
/**
140+
* Returns a list of the elements in the heap in in-order traversal.
141+
*
142+
* @return an ArrayList containing the elements in in-order
143+
*/
110144
public ArrayList<Integer> inOrder() {
111145
ArrayList<Integer> lst = new ArrayList<>();
112146
inOrderAux(root, lst);
113147
return new ArrayList<>(lst);
114148
}
115149

116-
// Auxiliary function for in_order
150+
/**
151+
* Auxiliary function for in-order traversal
152+
*
153+
* @param n the current node
154+
* @param lst the list to store the elements in in-order
155+
*/
117156
private void inOrderAux(Node n, ArrayList<Integer> lst) {
118157
if (n == null) {
119158
return;

src/test/java/com/thealgorithms/datastructures/heaps/LeftistHeapTest.java

Lines changed: 69 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,80 @@
66
public class LeftistHeapTest {
77

88
@Test
9-
void testLeftistHeap() {
9+
void testIsEmpty() {
10+
LeftistHeap heap = new LeftistHeap();
11+
Assertions.assertTrue(heap.isEmpty(), "Heap should be empty initially.");
12+
13+
heap.insert(10);
14+
Assertions.assertFalse(heap.isEmpty(), "Heap should not be empty after insertion.");
15+
16+
heap.clear();
17+
Assertions.assertTrue(heap.isEmpty(), "Heap should be empty after clearing.");
18+
}
19+
20+
@Test
21+
void testInsertAndExtractMin() {
1022
LeftistHeap heap = new LeftistHeap();
11-
Assertions.assertTrue(heap.isEmpty());
1223
heap.insert(6);
13-
Assertions.assertTrue(!heap.isEmpty());
1424
heap.insert(2);
1525
heap.insert(3);
1626
heap.insert(1);
17-
heap.inOrder();
18-
Assertions.assertTrue(heap.inOrder().toString().equals("[6, 2, 3, 1]"));
19-
Assertions.assertTrue(heap.extractMin() == 1);
20-
Assertions.assertTrue(heap.inOrder().toString().equals("[6, 2, 3]"));
27+
28+
Assertions.assertEquals(1, heap.extractMin(), "Minimum should be 1.");
29+
Assertions.assertEquals(2, heap.extractMin(), "Next minimum should be 2.");
30+
Assertions.assertEquals(3, heap.extractMin(), "Next minimum should be 3.");
31+
Assertions.assertEquals(6, heap.extractMin(), "Next minimum should be 6.");
32+
Assertions.assertEquals(-1, heap.extractMin(), "Extracting from an empty heap should return -1.");
33+
}
34+
35+
@Test
36+
void testMerge() {
37+
LeftistHeap heap1 = new LeftistHeap();
38+
heap1.insert(1);
39+
heap1.insert(3);
40+
heap1.insert(5);
41+
42+
LeftistHeap heap2 = new LeftistHeap();
43+
heap2.insert(2);
44+
heap2.insert(4);
45+
heap2.insert(6);
46+
47+
heap1.merge(heap2);
48+
49+
Assertions.assertEquals(1, heap1.extractMin(), "After merging, minimum should be 1.");
50+
Assertions.assertEquals(2, heap1.extractMin(), "Next minimum should be 2.");
51+
Assertions.assertEquals(3, heap1.extractMin(), "Next minimum should be 3.");
52+
Assertions.assertEquals(4, heap1.extractMin(), "Next minimum should be 4.");
53+
Assertions.assertEquals(5, heap1.extractMin(), "Next minimum should be 5.");
54+
Assertions.assertEquals(6, heap1.extractMin(), "Next minimum should be 6.");
55+
Assertions.assertEquals(-1, heap1.extractMin(), "Extracting from an empty heap should return -1.");
56+
}
57+
58+
@Test
59+
void testInOrderTraversal() {
60+
LeftistHeap heap = new LeftistHeap();
61+
heap.insert(10);
62+
heap.insert(5);
63+
heap.insert(20);
64+
heap.insert(15);
65+
heap.insert(30);
66+
67+
Assertions.assertEquals("[20, 15, 30, 5, 10]", heap.inOrder().toString(), "In-order traversal should match the expected output.");
68+
}
69+
70+
@Test
71+
void testMultipleExtractions() {
72+
LeftistHeap heap = new LeftistHeap();
73+
heap.insert(10);
74+
heap.insert(5);
75+
heap.insert(3);
2176
heap.insert(8);
22-
heap.insert(12);
23-
heap.insert(4);
24-
Assertions.assertTrue(heap.inOrder().toString().equals("[8, 3, 12, 2, 6, 4]"));
25-
heap.clear();
26-
Assertions.assertTrue(heap.isEmpty());
77+
78+
// Extract multiple elements
79+
Assertions.assertEquals(3, heap.extractMin());
80+
Assertions.assertEquals(5, heap.extractMin());
81+
Assertions.assertEquals(8, heap.extractMin());
82+
Assertions.assertEquals(10, heap.extractMin());
83+
Assertions.assertEquals(-1, heap.extractMin(), "Extracting from an empty heap should return -1.");
2784
}
2885
}

0 commit comments

Comments
 (0)