diff --git a/src/main/java/com/thealgorithms/sorts/MergeSortNoExtraSpace.java b/src/main/java/com/thealgorithms/sorts/MergeSortNoExtraSpace.java index 290c2df5..7aa3b56e 100644 --- a/src/main/java/com/thealgorithms/sorts/MergeSortNoExtraSpace.java +++ b/src/main/java/com/thealgorithms/sorts/MergeSortNoExtraSpace.java @@ -1,73 +1,88 @@ package com.thealgorithms.sorts; import java.util.Arrays; -import java.util.Scanner; -/*This code implements the mergeSort algorithm without extra space -For understanding about mergesort visit :https://www.geeksforgeeks.org/merge-sort/ +/** + * Implementation of Merge Sort without using extra space for merging. + * This implementation performs in-place merging to sort the array of integers. */ public final class MergeSortNoExtraSpace { private MergeSortNoExtraSpace() { } - public static void callMergeSort(int[] a, int n) { - int maxele = Arrays.stream(a).max().getAsInt() + 1; - mergeSort(a, 0, n - 1, maxele); + /** + * Sorts the array using in-place merge sort algorithm. + * + * @param array the array to be sorted + * @return the sorted array + * @throws IllegalArgumentException If the array contains negative numbers. + */ + public static int[] sort(int[] array) { + if (array.length == 0) { + return array; + } + if (Arrays.stream(array).anyMatch(s -> s < 0)) { + throw new IllegalArgumentException("Implementation cannot sort negative numbers."); + } + + final int maxElement = Arrays.stream(array).max().getAsInt() + 1; + mergeSort(array, 0, array.length - 1, maxElement); + return array; } - public static void mergeSort(int[] a, int start, int end, int maxele) { // this function divides the array into 2 halves + /** + * Recursively divides the array into two halves, sorts and merges them. + * + * @param array the array to be sorted + * @param start the starting index of the array + * @param end the ending index of the array + * @param maxElement the value greater than any element in the array, used for encoding + */ + public static void mergeSort(int[] array, int start, int end, int maxElement) { if (start < end) { - int mid = (start + end) / 2; - mergeSort(a, start, mid, maxele); - mergeSort(a, mid + 1, end, maxele); - implementMergeSort(a, start, mid, end, maxele); + final int middle = (start + end) >>> 1; + mergeSort(array, start, middle, maxElement); + mergeSort(array, middle + 1, end, maxElement); + merge(array, start, middle, end, maxElement); } } - public static void implementMergeSort(int[] a, int start, int mid, int end, - int maxele) { // implementation of mergesort + /** + * Merges two sorted subarrays [start...middle] and [middle+1...end] in place. + * + * @param array the array containing the subarrays to be merged + * @param start the starting index of the first subarray + * @param middle the ending index of the first subarray and starting index of the second subarray + * @param end the ending index of the second subarray + * @param maxElement the value greater than any element in the array, used for encoding + */ + private static void merge(int[] array, int start, int middle, int end, int maxElement) { int i = start; - int j = mid + 1; + int j = middle + 1; int k = start; - while (i <= mid && j <= end) { - if (a[i] % maxele <= a[j] % maxele) { - a[k] = a[k] + (a[i] % maxele) * maxele; + while (i <= middle && j <= end) { + if (array[i] % maxElement <= array[j] % maxElement) { + array[k] = array[k] + (array[i] % maxElement) * maxElement; k++; i++; } else { - a[k] = a[k] + (a[j] % maxele) * maxele; + array[k] = array[k] + (array[j] % maxElement) * maxElement; k++; j++; } } - while (i <= mid) { - a[k] = a[k] + (a[i] % maxele) * maxele; + while (i <= middle) { + array[k] = array[k] + (array[i] % maxElement) * maxElement; k++; i++; } while (j <= end) { - a[k] = a[k] + (a[j] % maxele) * maxele; + array[k] = array[k] + (array[j] % maxElement) * maxElement; k++; j++; } for (i = start; i <= end; i++) { - a[i] = a[i] / maxele; + array[i] = array[i] / maxElement; } } - - public static void main(String[] args) { - Scanner inp = new Scanner(System.in); - System.out.println("Enter array size"); - int n = inp.nextInt(); - int[] a = new int[n]; - System.out.println("Enter array elements"); - for (int i = 0; i < n; i++) { - a[i] = inp.nextInt(); - } - callMergeSort(a, n); - for (int i = 0; i < a.length; i++) { - System.out.print(a[i] + " "); - } - inp.close(); - } } diff --git a/src/test/java/com/thealgorithms/sorts/MergeSortNoExtraSpaceTest.java b/src/test/java/com/thealgorithms/sorts/MergeSortNoExtraSpaceTest.java new file mode 100644 index 00000000..5677a7c9 --- /dev/null +++ b/src/test/java/com/thealgorithms/sorts/MergeSortNoExtraSpaceTest.java @@ -0,0 +1,34 @@ +package com.thealgorithms.sorts; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.util.stream.Stream; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +public class MergeSortNoExtraSpaceTest { + record TestCase(int[] inputArray, int[] expectedArray) { + } + + static Stream provideTestCases() { + return Stream.of(new TestCase(new int[] {}, new int[] {}), new TestCase(new int[] {1}, new int[] {1}), new TestCase(new int[] {1, 2, 3, 4, 5}, new int[] {1, 2, 3, 4, 5}), new TestCase(new int[] {5, 4, 3, 2, 1}, new int[] {1, 2, 3, 4, 5}), + new TestCase(new int[] {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5}, new int[] {1, 1, 2, 3, 3, 4, 5, 5, 5, 6, 9}), new TestCase(new int[] {4, 2, 4, 3, 2, 1, 5}, new int[] {1, 2, 2, 3, 4, 4, 5}), new TestCase(new int[] {0, 0, 0, 0}, new int[] {0, 0, 0, 0}), + new TestCase(new int[] {1000, 500, 100, 50, 10, 5, 1}, new int[] {1, 5, 10, 50, 100, 500, 1000}), new TestCase(new int[] {1, 2, 3, 1, 2, 3, 1, 2, 3}, new int[] {1, 1, 1, 2, 2, 2, 3, 3, 3}), + new TestCase(new int[] {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, new int[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}), new TestCase(new int[] {2, 1}, new int[] {1, 2}), new TestCase(new int[] {1, 3, 2}, new int[] {1, 2, 3})); + } + + @ParameterizedTest + @MethodSource("provideTestCases") + public void testCountingSort(TestCase testCase) { + int[] outputArray = MergeSortNoExtraSpace.sort(testCase.inputArray); + assertArrayEquals(testCase.expectedArray, outputArray); + } + + @Test + public void testNegativeNumbers() { + int[] arrayWithNegatives = {1, -2, 3, -4}; + assertThrows(IllegalArgumentException.class, () -> MergeSortNoExtraSpace.sort(arrayWithNegatives)); + } +}