MergeSort: Simplify merge function (#3774)

* bug fix for CircularBuffer + refactoring + add unit tests

* change Insertion sort to classical implementation + add isSorted function to SortUtils + add SortUtilsRandomGenerator for generating random values and arrays

* little fix

* simplify merge function in MergeSort

* refactor one-liners

Co-authored-by: Debasish Biswas <debasishbsws.abc@gmail.com>
This commit is contained in:
Narek Karapetian
2022-11-24 14:24:17 -08:00
committed by GitHub
parent 260f1b2bee
commit 72468cc707
4 changed files with 44 additions and 54 deletions

View File

@ -1,5 +1,7 @@
package com.thealgorithms.sorts; package com.thealgorithms.sorts;
import static com.thealgorithms.sorts.SortUtils.less;
/** /**
* Generic merge sort algorithm. * Generic merge sort algorithm.
* *
@ -7,6 +9,9 @@ package com.thealgorithms.sorts;
*/ */
class MergeSort implements SortAlgorithm { class MergeSort implements SortAlgorithm {
@SuppressWarnings("rawtypes")
private static Comparable[] aux;
/** /**
* Generic merge sort algorithm implements. * Generic merge sort algorithm implements.
* *
@ -16,6 +21,7 @@ class MergeSort implements SortAlgorithm {
*/ */
@Override @Override
public <T extends Comparable<T>> T[] sort(T[] unsorted) { public <T extends Comparable<T>> T[] sort(T[] unsorted) {
aux = new Comparable[unsorted.length];
doSort(unsorted, 0, unsorted.length - 1); doSort(unsorted, 0, unsorted.length - 1);
return unsorted; return unsorted;
} }
@ -25,11 +31,7 @@ class MergeSort implements SortAlgorithm {
* @param left the first index of the array. * @param left the first index of the array.
* @param right the last index of the array. * @param right the last index of the array.
*/ */
private static <T extends Comparable<T>> void doSort( private static <T extends Comparable<T>> void doSort(T[] arr, int left, int right) {
T[] arr,
int left,
int right
) {
if (left < right) { if (left < right) {
int mid = (left + right) >>> 1; int mid = (left + right) >>> 1;
doSort(arr, left, mid); doSort(arr, left, mid);
@ -47,54 +49,21 @@ class MergeSort implements SortAlgorithm {
* @param right the last index of the array merges two parts of an array in * @param right the last index of the array merges two parts of an array in
* increasing order. * increasing order.
*/ */
private static <T extends Comparable<T>> void merge(
T[] arr,
int left,
int mid,
int right
) {
int length = right - left + 1;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
T[] temp = (T[]) new Comparable[length]; private static <T extends Comparable<T>> void merge(T[] arr, int left, int mid, int right) {
int i = left; int i = left, j = mid + 1;
int j = mid + 1; System.arraycopy(arr, left, aux, left, right + 1 - left);
int k = 0;
while (i <= mid && j <= right) { for (int k = left; k <= right; k++) {
if (arr[i].compareTo(arr[j]) <= 0) { if (j > right) {
temp[k++] = arr[i++]; arr[k] = (T) aux[i++];
} else if (i > mid) {
arr[k] = (T) aux[j++];
} else if (less(aux[j], aux[i])) {
arr[k] = (T) aux[j++];
} else { } else {
temp[k++] = arr[j++]; arr[k] = (T) aux[i++];
} }
} }
while (i <= mid) {
temp[k++] = arr[i++];
}
while (j <= right) {
temp[k++] = arr[j++];
}
System.arraycopy(temp, 0, arr, left, length);
}
/**
* Driver code
*/
public static void main(String[] args) {
MergeSort mergeSort = new MergeSort();
Integer[] arr = { 4, 23, 6, 78, 1, 54, 231, 9, 12 };
mergeSort.sort(arr);
for (int i = 0; i < arr.length - 1; ++i) {
assert arr[i] <= arr[i + 1];
}
String[] stringArray = { "c", "a", "e", "b", "d" };
mergeSort.sort(stringArray);
for (int i = 0; i < stringArray.length - 1; ++i) {
assert arr[i].compareTo(arr[i + 1]) <= 0;
}
} }
} }

View File

@ -35,4 +35,13 @@ public class SortUtilsRandomGenerator {
return random.nextDouble(); return random.nextDouble();
} }
/**
* Function to generate int value.
*
* @return int value [0, n)
*/
public static int generateInt(int n) {
return random.nextInt(n);
}
} }

View File

@ -106,7 +106,7 @@ class InsertionSortTest {
} }
private void testWithRandomArray(Function<Double[], Double[]> sortAlgorithm) { private void testWithRandomArray(Function<Double[], Double[]> sortAlgorithm) {
int randomSize = (int) (SortUtilsRandomGenerator.generateDouble() * 10_000); int randomSize = SortUtilsRandomGenerator.generateInt(10_000);
Double[] array = SortUtilsRandomGenerator.generateArray(randomSize); Double[] array = SortUtilsRandomGenerator.generateArray(randomSize);
Double[] sorted = sortAlgorithm.apply(array); Double[] sorted = sortAlgorithm.apply(array);
assertTrue(SortUtils.isSorted(sorted)); assertTrue(SortUtils.isSorted(sorted));

View File

@ -1,13 +1,19 @@
package com.thealgorithms.sorts; package com.thealgorithms.sorts;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class MergeSortTest { public class MergeSortTest {
private static MergeSort mergeSort= new MergeSort(); private MergeSort mergeSort;
@BeforeEach
void setUp() {
mergeSort = new MergeSort();
}
@Test @Test
void shouldAcceptWhenEmptyArrayIsPassed() { void shouldAcceptWhenEmptyArrayIsPassed() {
@ -79,5 +85,11 @@ public class MergeSortTest {
assertArrayEquals(expected, sorted); assertArrayEquals(expected, sorted);
} }
@Test
void shouldAcceptWhenRandomArrayIsPassed() {
int randomSize = SortUtilsRandomGenerator.generateInt(10_000);
Double[] array = SortUtilsRandomGenerator.generateArray(randomSize);
Double[] sorted = mergeSort.sort(array);
assertTrue(SortUtils.isSorted(sorted));
}
} }