Skip to content

refactor: cleanup RadixSort #5280

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 17 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,7 @@
* [OddEvenSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/OddEvenSortTest.java)
* [PancakeSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/PancakeSortTest.java)
* [QuickSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/QuickSortTest.java)
* [RadixSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/RadixSortTest.java)
* [SelectionSortRecursiveTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/SelectionSortRecursiveTest.java)
* [SelectionSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/SelectionSortTest.java)
* [ShellSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/ShellSortTest.java)
Expand Down
108 changes: 72 additions & 36 deletions src/main/java/com/thealgorithms/sorts/RadixSort.java
Original file line number Diff line number Diff line change
@@ -1,62 +1,98 @@
package com.thealgorithms.sorts;

import com.thealgorithms.maths.NumberOfDigits;
import java.util.Arrays;

final class RadixSort {
/**
* This class provides an implementation of the radix sort algorithm.
* It sorts an array of nonnegative integers in increasing order.
*/
public final class RadixSort {
private static final int BASE = 10;

private RadixSort() {
}

private static int getMax(int[] arr, int n) {
int mx = arr[0];
for (int i = 1; i < n; i++) {
if (arr[i] > mx) {
mx = arr[i];
}
/**
* Sorts an array of nonnegative integers using the radix sort algorithm.
*
* @param array the array to be sorted
* @return the sorted array
* @throws IllegalArgumentException if any negative integers are found
*/
public static int[] sort(int[] array) {
if (array.length == 0) {
return array;
}
return mx;
}

private static void countSort(int[] arr, int n, int exp) {
int[] output = new int[n];
int i;
int[] count = new int[10];
Arrays.fill(count, 0);
checkForNegativeInput(array);
radixSort(array);
return array;
}

for (i = 0; i < n; i++) {
count[(arr[i] / exp) % 10]++;
/**
* Checks if the array contains any negative integers.
*
* @param array the array to be checked
* @throws IllegalArgumentException if any negative integers are found
*/
private static void checkForNegativeInput(int[] array) {
for (int number : array) {
if (number < 0) {
throw new IllegalArgumentException("Array contains non-positive integers.");
}
}
}

for (i = 1; i < 10; i++) {
count[i] += count[i - 1];
private static void radixSort(int[] array) {
final int max = Arrays.stream(array).max().getAsInt();
for (int i = 0, exp = 1; i < NumberOfDigits.numberOfDigits(max); i++, exp *= BASE) {
countingSortByDigit(array, exp);
}
}

for (i = n - 1; i >= 0; i--) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}
/**
* A utility method to perform counting sort of array[] according to the digit represented by exp.
*
* @param array the array to be sorted
* @param exp the exponent representing the current digit position
*/
private static void countingSortByDigit(int[] array, int exp) {
int[] count = countDigits(array, exp);
accumulateCounts(count);
int[] output = buildOutput(array, exp, count);
copyOutput(array, output);
}

System.arraycopy(output, 0, arr, 0, n);
private static int[] countDigits(int[] array, int exp) {
int[] count = new int[BASE];
for (int i = 0; i < array.length; i++) {
count[getDigit(array[i], exp)]++;
}
return count;
}

private static void radixsort(int[] arr, int n) {
int m = getMax(arr, n);
private static int getDigit(int number, int position) {
return (number / position) % BASE;
}

for (int exp = 1; m / exp > 0; exp *= 10) {
countSort(arr, n, exp);
private static void accumulateCounts(int[] count) {
for (int i = 1; i < BASE; i++) {
count[i] += count[i - 1];
}
}

static void print(int[] arr, int n) {
for (int i = 0; i < n; i++) {
System.out.print(arr[i] + " ");
private static int[] buildOutput(int[] array, int exp, int[] count) {
int[] output = new int[array.length];
for (int i = array.length - 1; i >= 0; i--) {
int digit = getDigit(array[i], exp);
output[count[digit] - 1] = array[i];
count[digit]--;
}
return output;
}

public static void main(String[] args) {
int[] arr = {170, 45, 75, 90, 802, 24, 2, 66};
int n = arr.length;
radixsort(arr, n);
print(arr, n);
private static void copyOutput(int[] array, int[] output) {
System.arraycopy(output, 0, array, 0, array.length);
}
}
// Written by James Mc Dermott(theycallmemac)
30 changes: 30 additions & 0 deletions src/test/java/com/thealgorithms/sorts/RadixSortTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

public class RadixSortTest {
@ParameterizedTest
@MethodSource("provideTestCases")
public void test(int[] inputArray, int[] expectedArray) {
assertArrayEquals(RadixSort.sort(inputArray), expectedArray);
}

private static Stream<Arguments> provideTestCases() {
return Stream.of(Arguments.of(new int[] {170, 45, 75, 90, 802, 24, 2, 66}, new int[] {2, 24, 45, 66, 75, 90, 170, 802}), Arguments.of(new int[] {3, 3, 3, 3}, new int[] {3, 3, 3, 3}), Arguments.of(new int[] {9, 4, 6, 8, 14, 3}, new int[] {3, 4, 6, 8, 9, 14}),
Arguments.of(new int[] {10, 90, 49, 2, 1, 5, 23}, new int[] {1, 2, 5, 10, 23, 49, 90}), Arguments.of(new int[] {1, 3, 4, 2, 7, 8}, new int[] {1, 2, 3, 4, 7, 8}), Arguments.of(new int[] {}, new int[] {}), Arguments.of(new int[] {1}, new int[] {1}),
Arguments.of(new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9}, new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9}), Arguments.of(new int[] {9, 8, 7, 6, 5, 4, 3, 2, 1}, new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9}),
Arguments.of(new int[] {1000000000, 999999999, 888888888, 777777777}, new int[] {777777777, 888888888, 999999999, 1000000000}), Arguments.of(new int[] {123, 9, 54321, 123456789, 0}, new int[] {0, 9, 123, 54321, 123456789}));
}

@Test
public void testWithNegativeNumbers() {
assertThrows(IllegalArgumentException.class, () -> RadixSort.sort(new int[] {3, 1, 4, 1, 5, -9}));
}
}