refactor: SelectionSort like classes and their tests (#5265)

* Refactor: Adding test common approach, adding javadocs, renaming variables

* Refactor: Fix failed build, when generated test case for recursion is too big. To avoid stackoverflow

* Checkstyle: Adding newline to end of class

* refactor: simplify assign minIndex in recursiveSelectionSort, and improving SelectionSort

* checkstyle: adding newline to SelectionSort

---------

Co-authored-by: Alex Klymenko <alx@alx.com>
Co-authored-by: Piotr Idzik <65706193+vil02@users.noreply.github.com>
This commit is contained in:
Alex Klymenko 2024-06-29 11:04:58 +03:00 committed by GitHub
parent 0087444e9f
commit 20e7a3aca4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 45 additions and 84 deletions

View File

@ -1,46 +1,31 @@
package com.thealgorithms.sorts; package com.thealgorithms.sorts;
public class SelectionSort implements SortAlgorithm { public class SelectionSort implements SortAlgorithm {
/** /**
* Generic selection sort algorithm in increasing order. * Sorts an array of comparable elements in increasing order using the selection sort algorithm.
* *
* @param arr the array to be sorted. * @param array the array to be sorted
* @param <T> the class of array. * @param <T> the class of array elements
* @return sorted array. * @return the sorted array
*/ */
@Override @Override
public <T extends Comparable<T>> T[] sort(T[] arr) { public <T extends Comparable<T>> T[] sort(T[] array) {
int n = arr.length; // One by one move the boundary of the unsorted subarray
for (int i = 0; i < n - 1; i++) { for (int i = 0; i < array.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < n; j++) { // Swap the remaining minimum element with the current element
if (arr[minIndex].compareTo(arr[j]) > 0) { SortUtils.swap(array, i, findIndexOfMin(array, i));
minIndex = j;
} }
} return array;
if (minIndex != i) {
SortUtils.swap(arr, i, minIndex);
}
}
return arr;
} }
/** private static <T extends Comparable<T>> int findIndexOfMin(T[] array, final int start) {
* Driver Code int minIndex = start;
*/ for (int i = start + 1; i < array.length; i++) {
public static void main(String[] args) { if (array[i].compareTo(array[minIndex]) < 0) {
Integer[] arr = {4, 23, 6, 78, 1, 54, 231, 9, 12}; minIndex = i;
SelectionSort selectionSort = new SelectionSort();
Integer[] sorted = selectionSort.sort(arr);
for (int i = 0; i < sorted.length - 1; ++i) {
assert sorted[i] <= sorted[i + 1];
}
String[] strings = {"c", "a", "e", "b", "d"};
String[] sortedStrings = selectionSort.sort(strings);
for (int i = 0; i < sortedStrings.length - 1; ++i) {
assert strings[i].compareTo(strings[i + 1]) <= 0;
} }
} }
return minIndex;
}
} }

View File

@ -32,13 +32,7 @@ public class SelectionSortRecursive implements SortAlgorithm {
return; return;
} }
// Find the minimum element in the remaining unsorted array SortUtils.swap(array, index, findMinIndex(array, index));
final int minIndex = findMinIndex(array, index);
// Swap the found minimum element with the element at the current index
if (minIndex != index) {
SortUtils.swap(array, index, minIndex);
}
// Recursively call selection sort for the remaining array // Recursively call selection sort for the remaining array
recursiveSelectionSort(array, index + 1); recursiveSelectionSort(array, index + 1);
@ -47,20 +41,21 @@ public class SelectionSortRecursive implements SortAlgorithm {
/** /**
* Finds the index of the minimum element in the array starting from the given index. * Finds the index of the minimum element in the array starting from the given index.
* *
* @param array the array to search in. * @param array the array to search
* @param start the starting index. * @param start the starting index for the search
* @param <T> the type of the elements in the array, which must be Comparable. * @param <T> the type of elements in the array
* @return the index of the minimum element starting from the given index. * @return the index of the minimum element
*/ */
private static <T extends Comparable<T>> int findMinIndex(T[] array, int start) { private static <T extends Comparable<T>> int findMinIndex(T[] array, int start) {
int currentMinIndex = start; // Base case: if start is the last index, return start
if (start == array.length - 1) {
for (int currentIndex = start + 1; currentIndex < array.length; currentIndex++) { return start;
if (array[currentIndex].compareTo(array[currentMinIndex]) < 0) {
currentMinIndex = currentIndex;
}
} }
return currentMinIndex; // Recursive call to find the minimum index in the rest of the array
final int minIndexInRest = findMinIndex(array, start + 1);
// Return the index of the smaller element between array[start] and the minimum element in the rest of the array
return array[start].compareTo(array[minIndexInRest]) < 0 ? start : minIndexInRest;
} }
} }

View File

@ -5,4 +5,8 @@ public class SelectionSortRecursiveTest extends SortingAlgorithmTest {
SortAlgorithm getSortAlgorithm() { SortAlgorithm getSortAlgorithm() {
return new SelectionSortRecursive(); return new SelectionSortRecursive();
} }
protected int getGeneratedArraySize() {
return 5000;
}
} }

View File

@ -1,35 +1,8 @@
package com.thealgorithms.sorts; package com.thealgorithms.sorts;
import static org.junit.jupiter.api.Assertions.assertArrayEquals; class SelectionSortTest extends SortingAlgorithmTest {
@Override
import org.junit.jupiter.api.Test; SortAlgorithm getSortAlgorithm() {
return new SelectionSort();
class SelectionSortTest {
@Test
// valid test case
void integerArrTest() {
Integer[] arr = {4, 23, 6, 78, 1, 54, 231, 9, 12};
SelectionSort selectionSort = new SelectionSort();
assertArrayEquals(new Integer[] {1, 4, 6, 9, 12, 23, 54, 78, 231}, selectionSort.sort(arr));
}
@Test
// valid test case
void stringArrTest() {
String[] arr = {"c", "a", "e", "b", "d"};
SelectionSort selectionSort = new SelectionSort();
assertArrayEquals(new String[] {"a", "b", "c", "d", "e"}, selectionSort.sort(arr));
}
@Test
// invalid test case
void emptyArrTest() {
Integer[] arr = {};
SelectionSort selectionSort = new SelectionSort();
assertArrayEquals(new Integer[] {}, selectionSort.sort(arr));
} }
} }

View File

@ -11,6 +11,10 @@ import org.junit.jupiter.api.Test;
public abstract class SortingAlgorithmTest { public abstract class SortingAlgorithmTest {
abstract SortAlgorithm getSortAlgorithm(); abstract SortAlgorithm getSortAlgorithm();
protected int getGeneratedArraySize() {
return 10_000;
}
@Test @Test
void shouldAcceptWhenEmptyArrayIsPassed() { void shouldAcceptWhenEmptyArrayIsPassed() {
Integer[] array = new Integer[] {}; Integer[] array = new Integer[] {};
@ -153,7 +157,7 @@ public abstract class SortingAlgorithmTest {
@Test @Test
void shouldAcceptWhenRandomArrayIsPassed() { void shouldAcceptWhenRandomArrayIsPassed() {
int randomSize = SortUtilsRandomGenerator.generateInt(10_000); int randomSize = SortUtilsRandomGenerator.generateInt(getGeneratedArraySize());
Double[] array = SortUtilsRandomGenerator.generateArray(randomSize); Double[] array = SortUtilsRandomGenerator.generateArray(randomSize);
Double[] sorted = getSortAlgorithm().sort(array); Double[] sorted = getSortAlgorithm().sort(array);
assertTrue(SortUtils.isSorted(sorted)); assertTrue(SortUtils.isSorted(sorted));
@ -161,7 +165,7 @@ public abstract class SortingAlgorithmTest {
@Test @Test
void shouldAcceptWhenRandomListIsPassed() { void shouldAcceptWhenRandomListIsPassed() {
int randomSize = SortUtilsRandomGenerator.generateInt(10_000); int randomSize = SortUtilsRandomGenerator.generateInt(getGeneratedArraySize());
Double[] array = SortUtilsRandomGenerator.generateArray(randomSize); Double[] array = SortUtilsRandomGenerator.generateArray(randomSize);
List<Double> list = List.of(array); List<Double> list = List.of(array);
List<Double> sorted = getSortAlgorithm().sort(list); List<Double> sorted = getSortAlgorithm().sort(list);