Skip to content

Commit 1a20a90

Browse files
authored
Merge branch 'master' into refactor/radix_sort
2 parents dd3825b + 57878ca commit 1a20a90

File tree

4 files changed

+252
-69
lines changed

4 files changed

+252
-69
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,6 +865,7 @@
865865
* [CocktailShakerSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CocktailShakerSortTest.java)
866866
* [CountingSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/CountingSortTest.java)
867867
* [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)
868869
* [DualPivotQuickSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DualPivotQuickSortTest.java)
869870
* [DutchNationalFlagSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/DutchNationalFlagSortTest.java)
870871
* [ExchangeSortTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/sorts/ExchangeSortTest.java)
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: 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+
}

src/test/java/com/thealgorithms/sorts/SortingAlgorithmTest.java

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package com.thealgorithms.sorts;
22

33
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
4+
import static org.junit.jupiter.api.Assertions.assertEquals;
45
import static org.junit.jupiter.api.Assertions.assertIterableEquals;
56
import static org.junit.jupiter.api.Assertions.assertTrue;
67

78
import java.util.ArrayList;
9+
import java.util.Arrays;
810
import java.util.List;
11+
import java.util.Objects;
912
import org.junit.jupiter.api.Test;
1013

1114
public abstract class SortingAlgorithmTest {
@@ -171,4 +174,192 @@ void shouldAcceptWhenRandomListIsPassed() {
171174
List<Double> sorted = getSortAlgorithm().sort(list);
172175
assertTrue(SortUtils.isSorted(sorted));
173176
}
177+
178+
@Test
179+
public void shouldAcceptWhenArrayWithAllIdenticalValuesIsPassed() {
180+
Integer[] array = {1, 1, 1, 1};
181+
Integer[] sortedArray = getSortAlgorithm().sort(array);
182+
assertArrayEquals(new Integer[] {1, 1, 1, 1}, sortedArray);
183+
}
184+
185+
@Test
186+
public void shouldAcceptWhenListWithAllIdenticalValuesIsPassed() {
187+
List<Integer> list = Arrays.asList(1, 1, 1, 1);
188+
List<Integer> sortedList = getSortAlgorithm().sort(list);
189+
assertEquals(Arrays.asList(1, 1, 1, 1), sortedList);
190+
}
191+
192+
@Test
193+
public void shouldAcceptWhenArrayWithMixedPositiveAndNegativeValuesIsPassed() {
194+
Integer[] array = {-1, 3, -2, 5, 0};
195+
Integer[] sortedArray = getSortAlgorithm().sort(array);
196+
assertArrayEquals(new Integer[] {-2, -1, 0, 3, 5}, sortedArray);
197+
}
198+
199+
@Test
200+
public void shouldAcceptWhenListWithMixedPositiveAndNegativeValuesIsPassed() {
201+
List<Integer> list = Arrays.asList(-1, 3, -2, 5, 0);
202+
List<Integer> sortedList = getSortAlgorithm().sort(list);
203+
assertEquals(Arrays.asList(-2, -1, 0, 3, 5), sortedList);
204+
}
205+
206+
@Test
207+
public void shouldAcceptWhenArrayWithLargeNumbersIsPassed() {
208+
Long[] array = {10000000000L, 9999999999L, 10000000001L};
209+
Long[] sortedArray = getSortAlgorithm().sort(array);
210+
assertArrayEquals(new Long[] {9999999999L, 10000000000L, 10000000001L}, sortedArray);
211+
}
212+
213+
@Test
214+
public void shouldAcceptWhenListWithLargeNumbersIsPassed() {
215+
List<Long> list = Arrays.asList(10000000000L, 9999999999L, 10000000001L);
216+
List<Long> sortedList = getSortAlgorithm().sort(list);
217+
assertEquals(Arrays.asList(9999999999L, 10000000000L, 10000000001L), sortedList);
218+
}
219+
220+
@Test
221+
public void shouldAcceptWhenArrayWithMaxIntegerValuesIsPassed() {
222+
Integer[] array = {Integer.MAX_VALUE, Integer.MIN_VALUE, 0};
223+
Integer[] sortedArray = getSortAlgorithm().sort(array);
224+
assertArrayEquals(new Integer[] {Integer.MIN_VALUE, 0, Integer.MAX_VALUE}, sortedArray);
225+
}
226+
227+
@Test
228+
public void shouldAcceptWhenListWithMaxIntegerValuesIsPassed() {
229+
List<Integer> list = Arrays.asList(Integer.MAX_VALUE, Integer.MIN_VALUE, 0);
230+
List<Integer> sortedList = getSortAlgorithm().sort(list);
231+
assertEquals(Arrays.asList(Integer.MIN_VALUE, 0, Integer.MAX_VALUE), sortedList);
232+
}
233+
234+
@Test
235+
public void shouldAcceptWhenArrayWithMinIntegerValuesIsPassed() {
236+
Integer[] array = {Integer.MIN_VALUE, Integer.MAX_VALUE, 0};
237+
Integer[] sortedArray = getSortAlgorithm().sort(array);
238+
assertArrayEquals(new Integer[] {Integer.MIN_VALUE, 0, Integer.MAX_VALUE}, sortedArray);
239+
}
240+
241+
@Test
242+
public void shouldAcceptWhenListWithMinIntegerValuesIsPassed() {
243+
List<Integer> list = Arrays.asList(Integer.MIN_VALUE, Integer.MAX_VALUE, 0);
244+
List<Integer> sortedList = getSortAlgorithm().sort(list);
245+
assertEquals(Arrays.asList(Integer.MIN_VALUE, 0, Integer.MAX_VALUE), sortedList);
246+
}
247+
248+
@Test
249+
public void shouldAcceptWhenArrayWithSpecialCharactersIsPassed() {
250+
String[] array = {"!", "@", "#", "$"};
251+
String[] sortedArray = getSortAlgorithm().sort(array);
252+
assertArrayEquals(new String[] {"!", "#", "$", "@"}, sortedArray);
253+
}
254+
255+
@Test
256+
public void shouldAcceptWhenListWithSpecialCharactersIsPassed() {
257+
List<String> list = Arrays.asList("!", "@", "#", "$");
258+
List<String> sortedList = getSortAlgorithm().sort(list);
259+
assertEquals(Arrays.asList("!", "#", "$", "@"), sortedList);
260+
}
261+
262+
@Test
263+
public void shouldAcceptWhenArrayWithMixedCaseStringsIsPassed() {
264+
String[] array = {"apple", "Banana", "cherry", "Date"};
265+
String[] sortedArray = getSortAlgorithm().sort(array);
266+
assertArrayEquals(new String[] {"Banana", "Date", "apple", "cherry"}, sortedArray);
267+
}
268+
269+
@Test
270+
public void shouldAcceptWhenListWithMixedCaseStringsIsPassed() {
271+
List<String> list = Arrays.asList("apple", "Banana", "cherry", "Date");
272+
List<String> sortedList = getSortAlgorithm().sort(list);
273+
assertEquals(Arrays.asList("Banana", "Date", "apple", "cherry"), sortedList);
274+
}
275+
276+
@Test
277+
public void shouldHandleArrayWithNullValues() {
278+
Integer[] array = {3, null, 2, null, 1};
279+
org.junit.jupiter.api.Assertions.assertThrows(NullPointerException.class, () -> getSortAlgorithm().sort(array));
280+
}
281+
282+
@Test
283+
public void shouldHandleListWithNullValues() {
284+
List<Integer> list = Arrays.asList(3, null, 2, null, 1);
285+
org.junit.jupiter.api.Assertions.assertThrows(NullPointerException.class, () -> getSortAlgorithm().sort(list));
286+
}
287+
288+
static class CustomObject implements Comparable<CustomObject> {
289+
int value;
290+
291+
CustomObject(int value) {
292+
this.value = value;
293+
}
294+
295+
@Override
296+
public int compareTo(CustomObject o) {
297+
return Integer.compare(this.value, o.value);
298+
}
299+
300+
@Override
301+
public String toString() {
302+
return "CustomObject{"
303+
+ "value=" + value + '}';
304+
}
305+
306+
@Override
307+
public boolean equals(Object o) {
308+
if (this == o) {
309+
return true;
310+
}
311+
if (o == null || getClass() != o.getClass()) {
312+
return false;
313+
}
314+
CustomObject that = (CustomObject) o;
315+
return value == that.value;
316+
}
317+
318+
@Override
319+
public int hashCode() {
320+
return Objects.hashCode(value);
321+
}
322+
}
323+
324+
@Test
325+
public void shouldHandleArrayOfCustomObjects() {
326+
CustomObject[] array = {new CustomObject(3), new CustomObject(1), new CustomObject(2)};
327+
CustomObject[] sortedArray = getSortAlgorithm().sort(array);
328+
assertArrayEquals(new CustomObject[] {new CustomObject(1), new CustomObject(2), new CustomObject(3)}, sortedArray);
329+
}
330+
331+
@Test
332+
public void shouldHandleListOfCustomObjects() {
333+
List<CustomObject> list = Arrays.asList(new CustomObject(3), new CustomObject(1), new CustomObject(2));
334+
List<CustomObject> sortedList = getSortAlgorithm().sort(list);
335+
assertEquals(Arrays.asList(new CustomObject(1), new CustomObject(2), new CustomObject(3)), sortedList);
336+
}
337+
338+
@Test
339+
public void shouldHandleArrayOfFloatingPointNumbers() {
340+
Double[] array = {3.3, 2.2, 1.1, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY};
341+
Double[] sortedArray = getSortAlgorithm().sort(array);
342+
assertArrayEquals(new Double[] {Double.NEGATIVE_INFINITY, 1.1, 2.2, 3.3, Double.POSITIVE_INFINITY, Double.NaN}, sortedArray);
343+
}
344+
345+
@Test
346+
public void shouldHandleListOfFloatingPointNumbers() {
347+
List<Double> list = Arrays.asList(3.3, 2.2, 1.1, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY);
348+
List<Double> sortedList = getSortAlgorithm().sort(list);
349+
assertEquals(Arrays.asList(Double.NEGATIVE_INFINITY, 1.1, 2.2, 3.3, Double.POSITIVE_INFINITY, Double.NaN), sortedList);
350+
}
351+
352+
@Test
353+
public void shouldHandleArrayWithEmptyStrings() {
354+
String[] array = {"apple", "", "banana", ""};
355+
String[] sortedArray = getSortAlgorithm().sort(array);
356+
assertArrayEquals(new String[] {"", "", "apple", "banana"}, sortedArray);
357+
}
358+
359+
@Test
360+
public void shouldHandleListWithEmptyStrings() {
361+
List<String> list = Arrays.asList("apple", "", "banana", "");
362+
List<String> sortedList = getSortAlgorithm().sort(list);
363+
assertEquals(Arrays.asList("", "", "apple", "banana"), sortedList);
364+
}
174365
}

0 commit comments

Comments
 (0)