Skip to content

Commit 99ff516

Browse files
BranAndSceolanAntonia Stracksiriak
authored
Add Wigglesort (TheAlgorithms#3032)
Co-authored-by: Antonia Strack <antonia.strack@thm.mni.de> Co-authored-by: Andrii Siriak <siryaka@gmail.com>
1 parent 7c31c5b commit 99ff516

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package com.thealgorithms.sorts;
2+
3+
import java.util.Arrays;
4+
5+
import static com.thealgorithms.maths.Ceil.ceil;
6+
import static com.thealgorithms.maths.Floor.floor;
7+
import static com.thealgorithms.searches.QuickSelect.select;
8+
9+
/**
10+
* A wiggle sort implementation based on John L.s' answer in
11+
* https://cs.stackexchange.com/questions/125372/how-to-wiggle-sort-an-array-in-linear-time-complexity
12+
* Also have a look at: https://cs.stackexchange.com/questions/125372/how-to-wiggle-sort-an-array-in-linear-time-complexity?noredirect=1&lq=1
13+
* Not all arrays are wiggle-sortable. This algorithm will find some obviously not wiggle-sortable arrays and throw an error,
14+
* but there are some exceptions that won't be caught, for example [1, 2, 2].
15+
*/
16+
public class WiggleSort implements SortAlgorithm {
17+
@Override
18+
public <T extends Comparable<T>> T[] sort(T[] unsorted) {
19+
return wiggleSort(unsorted);
20+
}
21+
22+
private int mapIndex(int index, int n) {
23+
return ((2 * index + 1) % (n | 1));
24+
}
25+
26+
/**
27+
* Modified Dutch National Flag Sort. See also: sorts/DutchNationalFlagSort
28+
*
29+
* @param sortThis array to sort into group "greater", "equal" and "smaller" than median
30+
* @param median defines the groups
31+
* @param <T> extends interface Comparable
32+
*/
33+
private <T extends Comparable<T>> void triColorSort(T[] sortThis, T median) {
34+
int n = sortThis.length;
35+
int i = 0;
36+
int j = 0;
37+
int k = n - 1;
38+
while (j <= k) {
39+
if (0 < sortThis[mapIndex(j, n)].compareTo(median)) {
40+
SortUtils.swap(sortThis, mapIndex(j, n), mapIndex(i, n));
41+
i++;
42+
j++;
43+
} else if (0 > sortThis[mapIndex(j, n)].compareTo(median)) {
44+
SortUtils.swap(sortThis, mapIndex(j, n), mapIndex(k, n));
45+
k--;
46+
} else {
47+
j++;
48+
}
49+
}
50+
}
51+
52+
private <T extends Comparable<T>> T[] wiggleSort(T[] sortThis) {
53+
// find the median using quickSelect (if the result isn't in the array, use the next greater value)
54+
T median;
55+
56+
median = select(Arrays.<T>asList(sortThis), (int) floor(sortThis.length / 2.0));
57+
58+
int numMedians = 0;
59+
60+
for (T sortThi : sortThis) {
61+
if (0 == sortThi.compareTo(median)) {
62+
numMedians++;
63+
}
64+
}
65+
// added condition preventing off-by-one errors for odd arrays.
66+
// https://cs.stackexchange.com/questions/150886/how-to-find-wiggle-sortable-arrays-did-i-misunderstand-john-l-s-answer?noredirect=1&lq=1
67+
if (sortThis.length % 2 == 1 && numMedians == ceil(sortThis.length / 2.0)) {
68+
T smallestValue = select(Arrays.asList(sortThis), 0);
69+
if (!(0 == smallestValue.compareTo(median))) {
70+
throw new IllegalArgumentException("For odd Arrays if the median appears ceil(n/2) times, " +
71+
"the median has to be the smallest values in the array.");
72+
}
73+
}
74+
if (numMedians > ceil(sortThis.length / 2.0)) {
75+
throw new IllegalArgumentException("No more than half the number of values may be the same.");
76+
77+
}
78+
79+
triColorSort(sortThis, median);
80+
return sortThis;
81+
}
82+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.thealgorithms.sorts;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.util.Arrays;
6+
7+
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
8+
9+
10+
public class WiggleSortTest {
11+
@Test
12+
void WiggleTestNumbersEven(){
13+
WiggleSort wiggleSort = new WiggleSort();
14+
Integer[] values = {1, 2, 3, 4};
15+
Integer[] result = {1, 4, 2, 3};
16+
wiggleSort.sort(values);
17+
assertArrayEquals(values, result);
18+
}
19+
20+
@Test
21+
void WiggleTestNumbersOdd(){
22+
WiggleSort wiggleSort = new WiggleSort();
23+
Integer[] values = {1, 2, 3, 4, 5};
24+
Integer[] result = {3, 5, 1, 4, 2};
25+
wiggleSort.sort(values);
26+
assertArrayEquals(values, result);
27+
28+
}
29+
30+
@Test
31+
void WiggleTestNumbersOddDuplicates(){
32+
WiggleSort wiggleSort = new WiggleSort();
33+
Integer[] values = {7, 2, 2, 2, 5};
34+
Integer[] result = {2, 7, 2, 5, 2};
35+
wiggleSort.sort(values);
36+
assertArrayEquals(values, result);
37+
}
38+
39+
@Test
40+
void WiggleTestNumbersOddMultipleDuplicates(){
41+
WiggleSort wiggleSort = new WiggleSort();
42+
Integer[] values = {1, 1, 2, 2, 5};
43+
Integer[] result = {2, 5, 1, 2, 1};
44+
wiggleSort.sort(values);
45+
assertArrayEquals(values, result);
46+
}
47+
48+
@Test
49+
void WiggleTestNumbersEvenMultipleDuplicates(){
50+
WiggleSort wiggleSort = new WiggleSort();
51+
Integer[] values = {1, 1, 2, 2, 2, 5};
52+
Integer[] result = {2, 5, 1, 2, 1, 2};
53+
wiggleSort.sort(values);
54+
System.out.println(Arrays.toString(values));
55+
assertArrayEquals(values, result);
56+
}
57+
58+
@Test
59+
void WiggleTestNumbersEvenDuplicates(){
60+
WiggleSort wiggleSort = new WiggleSort();
61+
Integer[] values = {1, 2, 4, 4};
62+
Integer[] result = {1, 4, 2, 4};
63+
wiggleSort.sort(values);
64+
assertArrayEquals(values, result);
65+
}
66+
67+
@Test
68+
void WiggleTestStrings(){
69+
WiggleSort wiggleSort = new WiggleSort();
70+
String[] values = {"a", "b", "d", "c"};
71+
String[] result = {"a", "d", "b", "c"};
72+
wiggleSort.sort(values);
73+
assertArrayEquals(values, result);
74+
}
75+
}

0 commit comments

Comments
 (0)