Here is the code for queue-mergesort by Mordecai J. Golin and Robert Sedgewick:
com.github.coderodde.util.QueueMergesort.java:
package com.github.coderodde.util;
import java.util.Arrays;
import java.util.Comparator;
/**
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Apr 1, 2023)
* @since 1.6 (Apr 1, 2023)
*/
public class QueueMergesort {
private static final class ListItem<E> {
E datum;
ListItem<E> next;
ListItem(E datum) {
this.datum = datum;
}
}
private static final class Queue<E> {
private final ListItem<E>[] buffer;
private int headIndex = 0;
private int tailIndex = 0;
private int size = 0;
Queue(int bufferCapacity) {
this.buffer = new ListItem[bufferCapacity];
}
int size() {
return size;
}
ListItem<E> get() {
ListItem<E> listHead = buffer[headIndex];
headIndex = (headIndex + 1) % buffer.length;
size--;
return listHead;
}
void put(ListItem<E> tail) {
buffer[tailIndex] = tail;
tailIndex = (tailIndex + 1) % buffer.length;
size++;
}
}
public static <E> void sort(E[] array, Comparator<? super E> comparator) {
if (array.length < 2) {
return;
}
Queue<E> queue = new Queue(array.length);
for (E element : array) {
queue.put(new ListItem<>(element));
}
while (queue.size() > 1) {
ListItem<E> lst1 = queue.get();
ListItem<E> lst2 = queue.get();
queue.put(merge(lst1, lst2, comparator));
}
int index = 0;
for (ListItem<E> list = queue.get(); list != null; list = list.next) {
array[index++] = list.datum;
}
}
private static <E> ListItem<E> merge(ListItem<E> lst1,
ListItem<E> lst2,
Comparator<? super E> comparator) {
ListItem<E> mergedList;
ListItem<E> mergedListTail;
if (comparator.compare(lst1.datum, lst2.datum) <= 0) {
mergedList = lst1;
lst1 = lst1.next;
} else {
mergedList = lst2;
lst2 = lst2.next;
}
mergedListTail = mergedList;
while (lst1 != null && lst2 != null) {
if (comparator.compare(lst1.datum, lst2.datum) <= 0) {
mergedListTail.next = lst1;
mergedListTail = lst1;
lst1 = lst1.next;
} else {
mergedListTail.next = lst2;
mergedListTail = lst2;
lst2 = lst2.next;
}
}
if (lst1 != null) {
mergedListTail.next = lst1;
} else {
mergedListTail.next = lst2;
}
return mergedList;
}
public static void main(String[] args) {
Integer[] array = { 5, 2, 1, 4, 3 };
QueueMergesort.sort(array, Integer::compareTo);
System.out.println(Arrays.toString(array));
}
}
com.github.coderodde.util.QueueMergesortTest.java:
package com.github.coderodde.util;
import java.util.Arrays;
import java.util.Random;
import static junit.framework.Assert.assertTrue;
import org.junit.Test;
public class QueueMergesortTest {
private static final int TEST_RUNS = 100;
private static final int MAX_ARRAY_LENGTH = 1_000;
private static final int UPPER_ELEMENT_BOUND = 600;
@Test
public void bruteForceTest() {
Random random = new Random(100L);
for (int i = 0; i < TEST_RUNS; i++) {
int arrayLength = random.nextInt(MAX_ARRAY_LENGTH) + 1;
Integer[] array = getRandomArray(arrayLength, random);
Integer[] referenceArray = array.clone();
com.github.coderodde.util.QueueMergesort.sort(
array,
Integer::compareTo);
java.util.Arrays.sort(referenceArray, Integer::compareTo);
assertTrue(Arrays.equals(referenceArray, array));
}
}
private static Integer[] getRandomArray(int size, Random random) {
Integer[] array = new Integer[size];
for (int i = 0; i < array.length; i++) {
array[i] = random.nextInt(UPPER_ELEMENT_BOUND);
}
return array;
}
}
Critique request
As always, please tell me anything what comes to mind.