Skip to content

refactor: cleanup CountingSort #5275

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

Closed
wants to merge 15 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 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
3 changes: 3 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@
* [CocktailShakerSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CocktailShakerSort.java)
* [CombSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CombSort.java)
* [CountingSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CountingSort.java)
* [CountingSortUsingStream](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CountingSortUsingStream.java)
* [CycleSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CycleSort.java)
* [DNFSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DNFSort.java)
* [DualPivotQuickSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DualPivotQuickSort.java)
Expand Down Expand Up @@ -864,6 +865,8 @@
* [CircleSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CircleSortTest.java)
* [CocktailShakerSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CocktailShakerSortTest.java)
* [CombSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CombSortTest.java)
* [CountingSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CountingSortTest.java)
* [CountingSortUsingStream](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CountingSortUsingStream.java)
* [DualPivotQuickSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DualPivotQuickSortTest.java)
* [DutchNationalFlagSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DutchNationalFlagSortTest.java)
* [ExchangeSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/ExchangeSortTest.java)
Expand Down
90 changes: 25 additions & 65 deletions src/main/java/com/thealgorithms/sorts/CountingSort.java
Original file line number Diff line number Diff line change
@@ -1,93 +1,53 @@
package com.thealgorithms.sorts;

import static com.thealgorithms.sorts.SortUtils.print;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
* CountingSort is a generic implementation of the counting sort algorithm.
* This implementation sorts elements that implement the Comparable interface.
*
* @author Youssef Ali (https://github.com/youssefAli11997)
* @author Podshivalov Nikita (https://github.com/nikitap492)
*/
class CountingSort implements SortAlgorithm {

@Override
public <T extends Comparable<T>> T[] sort(T[] unsorted) {
return sort(Arrays.asList(unsorted)).toArray(unsorted);
public <T extends Comparable<T>> T[] sort(T[] array) {
return sort(Arrays.asList(array)).toArray(array);
}

/**
* This method implements the Generic Counting Sort
* Sorts the provided list using the counting sort algorithm.
*
* @param list The list to be sorted
* <p>
* Sorts the list in increasing order The method uses list elements as keys
* in the frequency map
* @param list The list to be sorted.
* @param <T> The type of elements in the list, must be Comparable.
* @return A sorted list in increasing order.
*/
@Override
public <T extends Comparable<T>> List<T> sort(List<T> list) {
Map<T, Integer> frequency = new TreeMap<>();
// The final output array
List<T> sortedArray = new ArrayList<>(list.size());

// Counting the frequency of @param array elements
list.forEach(v -> frequency.put(v, frequency.getOrDefault(v, 0) + 1));
Map<T, Integer> frequencyMap = computeFequencyMap(list);
return extractSortedArray(frequencyMap);
}

// Filling the sortedArray
for (Map.Entry<T, Integer> element : frequency.entrySet()) {
for (int j = 0; j < element.getValue(); j++) {
sortedArray.add(element.getKey());
private static <T extends Comparable<T>> List<T> extractSortedArray(Map<T, Integer> frequencyMap) {
List<T> sortedList = new ArrayList<>();
for (Map.Entry<T, Integer> entry : frequencyMap.entrySet()) {
for (int i = 0; i < entry.getValue(); i++) {
sortedList.add(entry.getKey());
}
}

return sortedArray;
}

/**
* Stream Counting Sort The same as method {@link CountingSort#sort(List)} }
* but this method uses stream API
*
* @param list The list to be sorted
*/
private static <T extends Comparable<T>> List<T> streamSort(List<T> list) {
return list.stream().collect(toMap(k -> k, v -> 1, (v1, v2) -> v1 + v2, TreeMap::new)).entrySet().stream().flatMap(entry -> IntStream.rangeClosed(1, entry.getValue()).mapToObj(t -> entry.getKey())).collect(toList());
return sortedList;
}

// Driver Program
public static void main(String[] args) {
// Integer Input
List<Integer> unsortedInts = Stream.of(4, 23, 6, 78, 1, 54, 23, 1, 9, 231, 9, 12).collect(toList());
CountingSort countingSort = new CountingSort();

System.out.println("Before Sorting:");
print(unsortedInts);

// Output => 1 1 4 6 9 9 12 23 23 54 78 231
System.out.println("After Sorting:");
print(countingSort.sort(unsortedInts));
System.out.println("After Sorting By Streams:");
print(streamSort(unsortedInts));

System.out.println("\n------------------------------\n");

// String Input
List<String> unsortedStrings = Stream.of("c", "a", "e", "b", "d", "a", "f", "g", "c").collect(toList());

System.out.println("Before Sorting:");
print(unsortedStrings);

// Output => a a b c c d e f g
System.out.println("After Sorting:");
print(countingSort.sort(unsortedStrings));

System.out.println("After Sorting By Streams:");
print(streamSort(unsortedStrings));
private static <T extends Comparable<T>> Map<T, Integer> computeFequencyMap(List<T> list) {
// TreeMap to maintain order of elements naturally.
Map<T, Integer> frequencyMap = new TreeMap<>();
for (T element : list) {
frequencyMap.put(element, frequencyMap.getOrDefault(element, 0) + 1);
}
return frequencyMap;
}
}
27 changes: 27 additions & 0 deletions src/main/java/com/thealgorithms/sorts/CountingSortUsingStream.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.thealgorithms.sorts;

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

import java.util.Arrays;
import java.util.List;
import java.util.TreeMap;
import java.util.stream.IntStream;

public class CountingSortUsingStream implements SortAlgorithm {
@Override
public <T extends Comparable<T>> T[] sort(T[] array) {
return streamSort(Arrays.asList(array)).toArray(array);
}

/**
* Sorts the provided list using the counting sort algorithm with the Stream API.
*
* @param list The list to be sorted.
* @param <T> The type of elements in the list, must be Comparable.
* @return A sorted list in increasing order.
*/
private static <T extends Comparable<T>> List<T> streamSort(List<T> list) {
return list.stream().collect(toMap(k -> k, v -> 1, Integer::sum, TreeMap::new)).entrySet().stream().flatMap(entry -> IntStream.rangeClosed(1, entry.getValue()).mapToObj(t -> entry.getKey())).collect(toList());
}
}
8 changes: 8 additions & 0 deletions src/test/java/com/thealgorithms/sorts/CountingSortTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.thealgorithms.sorts;

public class CountingSortTest extends SortingAlgorithmTest {
@Override
SortAlgorithm getSortAlgorithm() {
return new CountingSort();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.thealgorithms.sorts;

public class CountingSortUsingStreamTest extends SortingAlgorithmTest {
@Override
SortAlgorithm getSortAlgorithm() {
return new CountingSortUsingStream();
}
}