Skip to content

Commit 369cbeb

Browse files
authored
Merge branch 'master' into Branch_Smooth_Sort
2 parents cf1ce78 + 57878ca commit 369cbeb

File tree

6 files changed

+322
-144
lines changed

6 files changed

+322
-144
lines changed

DIRECTORY.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,8 +494,8 @@
494494
* [BucketSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/BucketSort.java)
495495
* [CircleSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CircleSort.java)
496496
* [CocktailShakerSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CocktailShakerSort.java)
497-
* [CombSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CombSort.java)
498497
* [CountingSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CountingSort.java)
498+
* [CombSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CombSort.java)
499499
* [CycleSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/CycleSort.java)
500500
* [DNFSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DNFSort.java)
501501
* [DualPivotQuickSort](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/sorts/DualPivotQuickSort.java)
@@ -863,7 +863,9 @@
863863
* [BucketSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/BucketSortTest.java)
864864
* [CircleSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CircleSortTest.java)
865865
* [CocktailShakerSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CocktailShakerSortTest.java)
866+
* [CountingSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CountingSortTest.java)
866867
* [CombSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CombSortTest.java)
868+
* [CycleSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CycleSortTest.java)
867869
* [DualPivotQuickSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DualPivotQuickSortTest.java)
868870
* [DutchNationalFlagSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DutchNationalFlagSortTest.java)
869871
* [ExchangeSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/ExchangeSortTest.java)
Lines changed: 41 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,60 @@
11
package com.thealgorithms.sorts;
22

3-
import static com.thealgorithms.sorts.SortUtils.print;
4-
import static java.util.stream.Collectors.toList;
5-
import static java.util.stream.Collectors.toMap;
6-
7-
import java.util.ArrayList;
83
import java.util.Arrays;
9-
import java.util.List;
10-
import java.util.Map;
11-
import java.util.TreeMap;
12-
import java.util.stream.IntStream;
13-
import java.util.stream.Stream;
144

155
/**
16-
* @author Youssef Ali (https://github.com/youssefAli11997)
17-
* @author Podshivalov Nikita (https://github.com/nikitap492)
6+
* A standard implementation of the Counting Sort algorithm for integer arrays.
7+
* This implementation has a time complexity of O(n + k), where n is the number
8+
* of elements in the input array and k is the range of the input.
9+
* It works only with integer arrays.
10+
*
11+
* The space complexity is O(k), where k is the range of the input integers.
12+
*
13+
* Note: This implementation handles negative integers as it
14+
* calculates the range based on the minimum and maximum values of the array.
15+
*
1816
*/
19-
class CountingSort implements SortAlgorithm {
20-
21-
@Override
22-
public <T extends Comparable<T>> T[] sort(T[] unsorted) {
23-
return sort(Arrays.asList(unsorted)).toArray(unsorted);
17+
public final class CountingSort {
18+
private CountingSort() {
2419
}
2520

2621
/**
27-
* This method implements the Generic Counting Sort
22+
* Sorts an array of integers using the Counting Sort algorithm.
2823
*
29-
* @param list The list to be sorted
30-
* <p>
31-
* Sorts the list in increasing order The method uses list elements as keys
32-
* in the frequency map
24+
* @param array the array to be sorted
25+
* @return the sorted array
3326
*/
34-
@Override
35-
public <T extends Comparable<T>> List<T> sort(List<T> list) {
36-
Map<T, Integer> frequency = new TreeMap<>();
37-
// The final output array
38-
List<T> sortedArray = new ArrayList<>(list.size());
39-
40-
// Counting the frequency of @param array elements
41-
list.forEach(v -> frequency.put(v, frequency.getOrDefault(v, 0) + 1));
42-
43-
// Filling the sortedArray
44-
for (Map.Entry<T, Integer> element : frequency.entrySet()) {
45-
for (int j = 0; j < element.getValue(); j++) {
46-
sortedArray.add(element.getKey());
47-
}
27+
public static int[] sort(int[] array) {
28+
if (array.length == 0) {
29+
return array;
4830
}
49-
50-
return sortedArray;
31+
final var stats = Arrays.stream(array).summaryStatistics();
32+
final int min = stats.getMin();
33+
int[] count = computeHistogram(array, min, stats.getMax() - min + 1);
34+
toCumulative(count);
35+
return reconstructSorted(count, min, array);
5136
}
5237

53-
/**
54-
* Stream Counting Sort The same as method {@link CountingSort#sort(List)} }
55-
* but this method uses stream API
56-
*
57-
* @param list The list to be sorted
58-
*/
59-
private static <T extends Comparable<T>> List<T> streamSort(List<T> list) {
60-
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());
38+
private static int[] computeHistogram(final int[] array, final int shift, final int spread) {
39+
int[] res = new int[spread];
40+
for (final var value : array) {
41+
res[value - shift]++;
42+
}
43+
return res;
6144
}
6245

63-
// Driver Program
64-
public static void main(String[] args) {
65-
// Integer Input
66-
List<Integer> unsortedInts = Stream.of(4, 23, 6, 78, 1, 54, 23, 1, 9, 231, 9, 12).collect(toList());
67-
CountingSort countingSort = new CountingSort();
68-
69-
System.out.println("Before Sorting:");
70-
print(unsortedInts);
71-
72-
// Output => 1 1 4 6 9 9 12 23 23 54 78 231
73-
System.out.println("After Sorting:");
74-
print(countingSort.sort(unsortedInts));
75-
System.out.println("After Sorting By Streams:");
76-
print(streamSort(unsortedInts));
77-
78-
System.out.println("\n------------------------------\n");
79-
80-
// String Input
81-
List<String> unsortedStrings = Stream.of("c", "a", "e", "b", "d", "a", "f", "g", "c").collect(toList());
82-
83-
System.out.println("Before Sorting:");
84-
print(unsortedStrings);
85-
86-
// Output => a a b c c d e f g
87-
System.out.println("After Sorting:");
88-
print(countingSort.sort(unsortedStrings));
46+
private static void toCumulative(int[] count) {
47+
for (int i = 1; i < count.length; i++) {
48+
count[i] += count[i - 1];
49+
}
50+
}
8951

90-
System.out.println("After Sorting By Streams:");
91-
print(streamSort(unsortedStrings));
52+
private static int[] reconstructSorted(final int[] cumulativeCount, final int shift, final int[] array) {
53+
int[] res = new int[array.length];
54+
for (int i = array.length - 1; i >= 0; i--) {
55+
res[cumulativeCount[array[i] - shift] - 1] = array[i];
56+
cumulativeCount[array[i] - shift]--;
57+
}
58+
return res;
9259
}
9360
}
Lines changed: 52 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,83 @@
11
package com.thealgorithms.sorts;
22

3-
import static com.thealgorithms.sorts.SortUtils.less;
4-
import static com.thealgorithms.sorts.SortUtils.print;
5-
63
/**
4+
* This class implements the cycle sort algorithm.
5+
* Cycle sort is an in-place sorting algorithm, unstable, and efficient for scenarios with limited memory usage.
76
* @author Podshivalov Nikita (https://github.com/nikitap492)
87
*/
98
class CycleSort implements SortAlgorithm {
10-
9+
/**
10+
* Sorts an array of comparable elements using the cycle sort algorithm.
11+
*
12+
* @param array the array to be sorted
13+
* @param <T> the type of elements in the array, must be comparable
14+
* @return the sorted array
15+
*/
1116
@Override
12-
public <T extends Comparable<T>> T[] sort(T[] arr) {
13-
int n = arr.length;
14-
15-
// traverse array elements
16-
for (int j = 0; j <= n - 2; j++) {
17-
// initialize item as starting point
18-
T item = arr[j];
19-
20-
// Find position where we put the item.
21-
int pos = j;
22-
for (int i = j + 1; i < n; i++) {
23-
if (less(arr[i], item)) {
17+
public <T extends Comparable<T>> T[] sort(T[] array) {
18+
for (int cycleStart = 0; cycleStart <= array.length - 2; cycleStart++) {
19+
T item = array[cycleStart];
20+
21+
// Find the position where we put the element
22+
int pos = cycleStart;
23+
for (int i = cycleStart + 1; i < array.length; i++) {
24+
if (SortUtils.less(array[i], item)) {
2425
pos++;
2526
}
2627
}
2728

28-
// If item is already in correct position
29-
if (pos == j) {
29+
// If the item is already in the correct position
30+
if (pos == cycleStart) {
3031
continue;
3132
}
3233

33-
// ignore all duplicate elements
34-
while (item.compareTo(arr[pos]) == 0) {
35-
pos += 1;
34+
// Ignore all duplicate elements
35+
while (item.compareTo(array[pos]) == 0) {
36+
pos++;
3637
}
3738

38-
// put the item to it's right position
39-
if (pos != j) {
40-
item = replace(arr, pos, item);
39+
// Put the item to its correct position
40+
if (pos != cycleStart) {
41+
item = replace(array, pos, item);
4142
}
4243

43-
// Rotate rest of the cycle
44-
while (pos != j) {
45-
pos = j;
44+
// Rotate the rest of the cycle
45+
while (pos != cycleStart) {
46+
pos = cycleStart;
4647

47-
// Find position where we put the element
48-
for (int i = j + 1; i < n; i++) {
49-
if (less(arr[i], item)) {
50-
pos += 1;
48+
// Find the position where we put the element
49+
for (int i = cycleStart + 1; i < array.length; i++) {
50+
if (SortUtils.less(array[i], item)) {
51+
pos++;
5152
}
5253
}
5354

54-
// ignore all duplicate elements
55-
while (item.compareTo(arr[pos]) == 0) {
56-
pos += 1;
55+
// Ignore all duplicate elements
56+
while (item.compareTo(array[pos]) == 0) {
57+
pos++;
5758
}
5859

59-
// put the item to it's right position
60-
if (item != arr[pos]) {
61-
item = replace(arr, pos, item);
60+
// Put the item to its correct position
61+
if (item != array[pos]) {
62+
item = replace(array, pos, item);
6263
}
6364
}
6465
}
65-
66-
return arr;
67-
}
68-
69-
private <T extends Comparable<T>> T replace(T[] arr, int pos, T item) {
70-
T temp = item;
71-
item = arr[pos];
72-
arr[pos] = temp;
73-
return item;
66+
return array;
7467
}
7568

76-
public static void main(String[] args) {
77-
Integer[] arr = {
78-
4,
79-
23,
80-
6,
81-
78,
82-
1,
83-
26,
84-
11,
85-
23,
86-
0,
87-
-6,
88-
3,
89-
54,
90-
231,
91-
9,
92-
12,
93-
};
94-
CycleSort cycleSort = new CycleSort();
95-
cycleSort.sort(arr);
96-
97-
System.out.println("After sort : ");
98-
print(arr);
69+
/**
70+
* Replaces an element in the array with the given item and returns the replaced item.
71+
*
72+
* @param array the array in which the replacement will occur
73+
* @param pos the position at which the replacement will occur
74+
* @param item the item to be placed in the array
75+
* @param <T> the type of elements in the array, must be comparable
76+
* @return the replaced item
77+
*/
78+
private <T extends Comparable<T>> T replace(T[] array, int pos, T item) {
79+
T replacedItem = array[pos];
80+
array[pos] = item;
81+
return replacedItem;
9982
}
10083
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.thealgorithms.sorts;
2+
3+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
5+
import java.util.stream.Stream;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.MethodSource;
8+
9+
public class CountingSortTest {
10+
11+
record TestCase(int[] inputArray, int[] expectedArray) {
12+
}
13+
14+
static Stream<TestCase> provideTestCases() {
15+
return Stream.of(new TestCase(new int[] {}, new int[] {}), new TestCase(new int[] {4}, new int[] {4}), new TestCase(new int[] {6, 1, 99, 27, 15, 23, 36}, new int[] {1, 6, 15, 23, 27, 36, 99}), new TestCase(new int[] {6, 1, 27, 15, 23, 27, 36, 23}, new int[] {1, 6, 15, 23, 23, 27, 27, 36}),
16+
new TestCase(new int[] {5, 5, 5, 5, 5}, new int[] {5, 5, 5, 5, 5}), 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}, new int[] {-9, -1, 1, 3, 4, 5}),
17+
new TestCase(new int[] {0, 0, 0, 0}, new int[] {0, 0, 0, 0}), new TestCase(new int[] {3, 3, -1, -1, 2, 2, 0, 0}, new int[] {-1, -1, 0, 0, 2, 2, 3, 3}), new TestCase(new int[] {-3, -2, -1, -5, -4}, new int[] {-5, -4, -3, -2, -1}),
18+
new TestCase(new int[] {1000, 500, 100, 50, 10, 5, 1}, new int[] {1, 5, 10, 50, 100, 500, 1000}), new TestCase(new int[] {4, -5, 10, 0}, new int[] {-5, 0, 4, 10}));
19+
}
20+
21+
@ParameterizedTest
22+
@MethodSource("provideTestCases")
23+
public void testCountingSortException(TestCase testCase) {
24+
int[] outputArray = CountingSort.sort(testCase.inputArray);
25+
assertArrayEquals(testCase.expectedArray, outputArray);
26+
}
27+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package com.thealgorithms.sorts;
2+
3+
public class CycleSortTest extends SortingAlgorithmTest {
4+
@Override
5+
SortAlgorithm getSortAlgorithm() {
6+
return new CycleSort();
7+
}
8+
}

0 commit comments

Comments
 (0)