Skip to content

Commit 3a8b04a

Browse files
authored
Enhance docs, add tests in MergeKSortedLinkedList (#5995)
1 parent cd87dc3 commit 3a8b04a

File tree

3 files changed

+158
-21
lines changed

3 files changed

+158
-21
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,7 @@
830830
* lists
831831
* [CircleLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CircleLinkedListTest.java)
832832
* [CreateAndDetectLoopTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/CreateAndDetectLoopTest.java)
833+
* [MergeKSortedLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/MergeKSortedLinkedListTest.java)
833834
* [MergeSortedArrayListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/MergeSortedArrayListTest.java)
834835
* [MergeSortedSinglyLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/MergeSortedSinglyLinkedListTest.java)
835836
* [QuickSortLinkedListTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/datastructures/lists/QuickSortLinkedListTest.java)
Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,94 @@
11
package com.thealgorithms.datastructures.lists;
22

3-
import java.util.Arrays;
43
import java.util.Comparator;
54
import java.util.PriorityQueue;
65

76
/**
7+
* The MergeKSortedLinkedList class provides a method to merge multiple sorted linked lists
8+
* into a single sorted linked list.
9+
* This implementation uses a min-heap (priority queue) to efficiently
10+
* find the smallest node across all lists, thus optimizing the merge process.
11+
*
12+
* <p>Example usage:
13+
* <pre>
14+
* Node list1 = new Node(1, new Node(4, new Node(5)));
15+
* Node list2 = new Node(1, new Node(3, new Node(4)));
16+
* Node list3 = new Node(2, new Node(6));
17+
* Node[] lists = { list1, list2, list3 };
18+
*
19+
* MergeKSortedLinkedList merger = new MergeKSortedLinkedList();
20+
* Node mergedHead = merger.mergeKList(lists, lists.length);
21+
* </pre>
22+
* </p>
23+
*
24+
* <p>This class is designed to handle nodes of integer linked lists and can be expanded for additional data types if needed.</p>
25+
*
826
* @author Arun Pandey (https://github.com/pandeyarun709)
927
*/
1028
public class MergeKSortedLinkedList {
1129

1230
/**
13-
* This function merge K sorted LinkedList
31+
* Merges K sorted linked lists into a single sorted linked list.
1432
*
15-
* @param a array of LinkedList
16-
* @param n size of array
17-
* @return node
33+
* <p>This method uses a priority queue (min-heap) to repeatedly extract the smallest node from the heads of all the lists,
34+
* then inserts the next node from that list into the heap. The process continues until all nodes have been processed,
35+
* resulting in a fully merged and sorted linked list.</p>
36+
*
37+
* @param a Array of linked list heads to be merged.
38+
* @param n Number of linked lists.
39+
* @return Head of the merged sorted linked list.
1840
*/
1941
Node mergeKList(Node[] a, int n) {
20-
// Min Heap
21-
PriorityQueue<Node> min = new PriorityQueue<>(Comparator.comparingInt(x -> x.data));
42+
if (a == null || n == 0) {
43+
return null;
44+
}
2245

23-
// adding head of all linkedList in min heap
24-
min.addAll(Arrays.asList(a).subList(0, n));
46+
// Min Heap to store nodes based on their values for efficient retrieval of the smallest element.
47+
PriorityQueue<Node> minHeap = new PriorityQueue<>(Comparator.comparingInt(x -> x.data));
2548

26-
// Make new head among smallest heads in K linkedList
27-
Node head = min.poll();
28-
min.add(head.next);
29-
Node curr = head;
49+
// Initialize the min-heap with the head of each non-null linked list
50+
for (Node node : a) {
51+
if (node != null) {
52+
minHeap.add(node);
53+
}
54+
}
55+
56+
// Start merging process
57+
Node head = minHeap.poll(); // Smallest head is the initial head of the merged list
58+
if (head != null && head.next != null) {
59+
minHeap.add(head.next);
60+
}
3061

31-
// merging LinkedList
32-
while (!min.isEmpty()) {
33-
Node temp = min.poll();
62+
Node curr = head;
63+
while (!minHeap.isEmpty()) {
64+
Node temp = minHeap.poll();
3465
curr.next = temp;
3566
curr = temp;
3667

37-
// Add Node in min Heap only if temp.next is not null
68+
// Add the next node in the current list to the heap if it exists
3869
if (temp.next != null) {
39-
min.add(temp.next);
70+
minHeap.add(temp.next);
4071
}
4172
}
4273

4374
return head;
4475
}
4576

46-
private final class Node {
77+
/**
78+
* Represents a node in the linked list.
79+
*/
80+
static class Node {
81+
int data;
82+
Node next;
83+
84+
Node(int data) {
85+
this.data = data;
86+
this.next = null;
87+
}
4788

48-
private int data;
49-
private Node next;
89+
Node(int data, Node next) {
90+
this.data = data;
91+
this.next = next;
92+
}
5093
}
5194
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package com.thealgorithms.datastructures.lists;
2+
3+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
import static org.junit.jupiter.api.Assertions.assertNull;
5+
6+
import com.thealgorithms.datastructures.lists.MergeKSortedLinkedList.Node;
7+
import java.util.Arrays;
8+
import org.junit.jupiter.api.Test;
9+
10+
class MergeKSortedLinkedListTest {
11+
12+
@Test
13+
void testMergeKLists() {
14+
Node list1 = new Node(1, new Node(4, new Node(5)));
15+
Node list2 = new Node(1, new Node(3, new Node(4)));
16+
Node list3 = new Node(2, new Node(6));
17+
Node[] lists = {list1, list2, list3};
18+
19+
MergeKSortedLinkedList merger = new MergeKSortedLinkedList();
20+
Node mergedHead = merger.mergeKList(lists, lists.length);
21+
22+
int[] expectedValues = {1, 1, 2, 3, 4, 4, 5, 6};
23+
int[] actualValues = getListValues(mergedHead);
24+
assertArrayEquals(expectedValues, actualValues, "Merged list values do not match the expected sorted order.");
25+
}
26+
27+
@Test
28+
void testMergeEmptyLists() {
29+
Node[] lists = {null, null, null};
30+
31+
MergeKSortedLinkedList merger = new MergeKSortedLinkedList();
32+
Node mergedHead = merger.mergeKList(lists, lists.length);
33+
34+
assertNull(mergedHead, "Merged list should be null when all input lists are empty.");
35+
}
36+
37+
@Test
38+
void testMergeSingleList() {
39+
Node list1 = new Node(1, new Node(3, new Node(5)));
40+
Node[] lists = {list1};
41+
42+
MergeKSortedLinkedList merger = new MergeKSortedLinkedList();
43+
Node mergedHead = merger.mergeKList(lists, lists.length);
44+
45+
int[] expectedValues = {1, 3, 5};
46+
int[] actualValues = getListValues(mergedHead);
47+
assertArrayEquals(expectedValues, actualValues, "Merged list should match the single input list when only one list is provided.");
48+
}
49+
50+
@Test
51+
void testMergeListsOfDifferentLengths() {
52+
Node list1 = new Node(1, new Node(3, new Node(5)));
53+
Node list2 = new Node(2, new Node(4));
54+
Node list3 = new Node(6);
55+
Node[] lists = {list1, list2, list3};
56+
57+
MergeKSortedLinkedList merger = new MergeKSortedLinkedList();
58+
Node mergedHead = merger.mergeKList(lists, lists.length);
59+
60+
int[] expectedValues = {1, 2, 3, 4, 5, 6};
61+
int[] actualValues = getListValues(mergedHead);
62+
assertArrayEquals(expectedValues, actualValues, "Merged list values do not match expected sorted order for lists of different lengths.");
63+
}
64+
65+
@Test
66+
void testMergeSingleElementLists() {
67+
Node list1 = new Node(1);
68+
Node list2 = new Node(3);
69+
Node list3 = new Node(2);
70+
Node[] lists = {list1, list2, list3};
71+
72+
MergeKSortedLinkedList merger = new MergeKSortedLinkedList();
73+
Node mergedHead = merger.mergeKList(lists, lists.length);
74+
75+
int[] expectedValues = {1, 2, 3};
76+
int[] actualValues = getListValues(mergedHead);
77+
assertArrayEquals(expectedValues, actualValues, "Merged list values do not match expected sorted order for single-element lists.");
78+
}
79+
80+
/**
81+
* Helper method to extract values from the linked list into an array for assertion.
82+
*/
83+
private int[] getListValues(Node head) {
84+
int[] values = new int[100]; // assuming max length for simplicity
85+
int i = 0;
86+
Node curr = head;
87+
while (curr != null) {
88+
values[i++] = curr.data;
89+
curr = curr.next;
90+
}
91+
return Arrays.copyOf(values, i); // return only filled part
92+
}
93+
}

0 commit comments

Comments
 (0)