Skip to content

refactor: MergeSortNoExtraSpace #5277

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 9, 2024
91 changes: 53 additions & 38 deletions src/main/java/com/thealgorithms/sorts/MergeSortNoExtraSpace.java
Original file line number Diff line number Diff line change
@@ -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;
}
}

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] + " ");
array[i] = array[i] / maxElement;
}
inp.close();
}
}
Original file line number Diff line number Diff line change
@@ -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<TestCase> 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));
}
}