Skip to content

Commit e056b72

Browse files
committed
Added an inplace version of merge sort and fixed a problem I introduced
into radix sort. Also a bit of code clean-up in most of the sorting classes.
1 parent 50a36f1 commit e056b72

File tree

10 files changed

+122
-40
lines changed

10 files changed

+122
-40
lines changed

src/com/jwetherell/algorithms/sorts/AmericanFlagSort.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@ public class AmericanFlagSort {
2222

2323
private static final int NUMBER_OF_BUCKETS = 10; // 10 for base 10 numbers
2424

25-
private AmericanFlagSort() {
26-
}
25+
private AmericanFlagSort() { }
2726

2827
public static Integer[] sort(Integer[] unsorted) {
2928
int numberOfDigits = getMaxNumberOfDigits(unsorted); // Max number of digits

src/com/jwetherell/algorithms/sorts/BubbleSort.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
*/
1919
public class BubbleSort<T extends Comparable<T>> {
2020

21-
private BubbleSort() {
22-
}
21+
private BubbleSort() { }
2322

2423
public static <T extends Comparable<T>> T[] sort(T[] unsorted) {
2524
boolean swapped = true;

src/com/jwetherell/algorithms/sorts/CountingSort.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
*/
2121
public class CountingSort {
2222

23-
private CountingSort() {
24-
}
23+
private CountingSort() { }
2524

2625
public static Integer[] sort(Integer[] unsorted) {
2726
int maxValue = findMax(unsorted);

src/com/jwetherell/algorithms/sorts/HeapSort.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
*/
1919
public class HeapSort<T extends Comparable<T>> {
2020

21-
private HeapSort() {
22-
}
21+
private HeapSort() { }
2322

2423
public static <T extends Comparable<T>> T[] sort(T[] unsorted) {
2524
createHeap(unsorted);

src/com/jwetherell/algorithms/sorts/InsertionSort.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@
1818
*/
1919
public class InsertionSort<T extends Comparable<T>> {
2020

21-
private InsertionSort() {
22-
}
21+
private InsertionSort() { }
2322

2423
public static <T extends Comparable<T>> T[] sort(T[] unsorted) {
2524
int length = unsorted.length;

src/com/jwetherell/algorithms/sorts/MergeSort.java

+35-9
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,25 @@
1717
*/
1818
public class MergeSort<T extends Comparable<T>> {
1919

20-
private MergeSort() {
21-
}
20+
public static enum SPACE_TYPE { IN_PLACE, NOT_IN_PLACE }
21+
22+
private MergeSort() { }
2223

23-
public static <T extends Comparable<T>> T[] sort(T[] unsorted) {
24-
sort(0, unsorted.length, unsorted);
24+
public static <T extends Comparable<T>> T[] sort(SPACE_TYPE type, T[] unsorted) {
25+
sort(type, 0, unsorted.length, unsorted);
2526
return unsorted;
2627
}
2728

28-
private static <T extends Comparable<T>> void sort(int start, int length, T[] unsorted) {
29+
private static <T extends Comparable<T>> void sort(SPACE_TYPE type, int start, int length, T[] unsorted) {
2930
if (length > 2) {
3031
int aLength = (int) Math.floor(length / 2);
3132
int bLength = length - aLength;
32-
sort(start, aLength, unsorted);
33-
sort(start + aLength, bLength, unsorted);
34-
merge(start, aLength, start + aLength, bLength, unsorted);
33+
sort(type, start, aLength, unsorted);
34+
sort(type, start + aLength, bLength, unsorted);
35+
if (type == SPACE_TYPE.IN_PLACE)
36+
mergeInPlace(start, aLength, start + aLength, bLength, unsorted);
37+
else
38+
mergeWithExtraStorage(start, aLength, start + aLength, bLength, unsorted);
3539
} else if (length == 2) {
3640
T e = unsorted[start + 1];
3741
if (e.compareTo(unsorted[start]) < 0) {
@@ -41,8 +45,30 @@ private static <T extends Comparable<T>> void sort(int start, int length, T[] un
4145
}
4246
}
4347

48+
private static <T extends Comparable<T>> void mergeInPlace(int aStart, int aLength, int bStart, int bLength, T[] unsorted) {
49+
int i = aStart;
50+
int j = bStart;
51+
int aSize = aStart + aLength;
52+
int bSize = bStart + bLength;
53+
while (i < aSize && j < bSize) {
54+
T a = unsorted[i];
55+
T b = unsorted[j];
56+
if (b.compareTo(a) < 0) {
57+
// Shift everything to the right one spot
58+
System.arraycopy(unsorted, i, unsorted, i+1, j-i);
59+
unsorted[i] = b;
60+
i++;
61+
j++;
62+
aSize++;
63+
} else {
64+
i++;
65+
}
66+
}
67+
}
68+
69+
4470
@SuppressWarnings("unchecked")
45-
private static <T extends Comparable<T>> void merge(int aStart, int aLength, int bStart, int bLength, T[] unsorted) {
71+
private static <T extends Comparable<T>> void mergeWithExtraStorage(int aStart, int aLength, int bStart, int bLength, T[] unsorted) {
4672
int count = 0;
4773
T[] output = (T[]) new Comparable[aLength + bLength];
4874
int i = aStart;

src/com/jwetherell/algorithms/sorts/RadixSort.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ public class RadixSort {
2525

2626
private static final int NUMBER_OF_BUCKETS = 10; // 10 for base 10 numbers
2727

28-
private RadixSort() {
29-
}
28+
private RadixSort() { }
3029

3130
public static Integer[] sort(Integer[] unsorted) {
3231
int[][] buckets = new int[NUMBER_OF_BUCKETS][10];
@@ -78,6 +77,6 @@ private static int[] add(int integer, int[] bucket) {
7877
}
7978
result[size] = integer;
8079
result[0] = ++size;
81-
return bucket;
80+
return result;
8281
}
8382
}

src/com/jwetherell/algorithms/sorts/ShellSort.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@
2121
*/
2222
public abstract class ShellSort<T extends Comparable<T>> {
2323

24-
private ShellSort() {
25-
}
24+
private ShellSort() { }
2625

2726
public static <T extends Comparable<T>> T[] sort(int[] shells, T[] unsorted) {
2827
for (int gap : shells) {

src/com/jwetherell/algorithms/sorts/test/Sorts.java

+15-4
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,24 @@ public void testShellsSorts() {
7878
}
7979

8080
@Test
81-
public void testMergeSorts() {
81+
public void testMergeSortsInPlace() {
8282
// Merge sort
83-
Integer[] result = MergeSort.sort(unsorted.clone());
83+
Integer[] result = MergeSort.sort(MergeSort.SPACE_TYPE.IN_PLACE, unsorted.clone());
8484
assertTrue("Merge sort unsorted error. result="+print(result), check(result));
85-
result = MergeSort.sort(sorted.clone());
85+
result = MergeSort.sort(MergeSort.SPACE_TYPE.IN_PLACE, sorted.clone());
8686
assertTrue("Merge sort sorted error. result="+print(result), check(result));
87-
result = MergeSort.sort(reverse.clone());
87+
result = MergeSort.sort(MergeSort.SPACE_TYPE.IN_PLACE, reverse.clone());
88+
assertTrue("merge sort reverse error. result="+print(result), check(result));
89+
}
90+
91+
@Test
92+
public void testMergeSortsNotInPlace() {
93+
// Merge sort
94+
Integer[] result = MergeSort.sort(MergeSort.SPACE_TYPE.NOT_IN_PLACE, unsorted.clone());
95+
assertTrue("Merge sort unsorted error. result="+print(result), check(result));
96+
result = MergeSort.sort(MergeSort.SPACE_TYPE.NOT_IN_PLACE, sorted.clone());
97+
assertTrue("Merge sort sorted error. result="+print(result), check(result));
98+
result = MergeSort.sort(MergeSort.SPACE_TYPE.NOT_IN_PLACE, reverse.clone());
8899
assertTrue("merge sort reverse error. result="+print(result), check(result));
89100
}
90101

src/com/jwetherell/algorithms/sorts/timing/SortsTiming.java

+64-12
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ public class SortsTiming {
2828
private static final double[] bubbleResults = new double[1 * 3];
2929
private static int shellCount = 0;
3030
private static final double[] shellResults = new double[1 * 3];
31-
private static int mergeCount = 0;
32-
private static final double[] mergeResults = new double[1 * 3];
31+
private static int mergeInPlaceCount = 0;
32+
private static final double[] mergeInPlaceResults = new double[1 * 3];
33+
private static int mergeNotInPlaceCount = 0;
34+
private static final double[] mergeNotInPlaceResults = new double[1 * 3];
3335
private static int quickCount = 0;
3436
private static final double[] quickResults = new double[3 * 3];
3537
private static int heapCount = 0;
@@ -44,7 +46,8 @@ public class SortsTiming {
4446
private static final boolean showInsertion = true;
4547
private static final boolean showBubble = true;
4648
private static final boolean showShell = true;
47-
private static final boolean showMerge = true;
49+
private static final boolean showMergeInPlace = true;
50+
private static final boolean showMergeNotInPlace = true;
4851
private static final boolean showQuick = true;
4952
private static final boolean showHeap = true;
5053
private static final boolean showCounting = true;
@@ -221,10 +224,10 @@ public static void main(String[] args) {
221224
System.out.flush();
222225
}
223226

224-
if (showMerge) {
227+
if (showMergeNotInPlace) {
225228
// Merge sort
226229
long bMerge = System.nanoTime();
227-
Integer[] result = MergeSort.sort(unsorted.clone());
230+
Integer[] result = MergeSort.sort(MergeSort.SPACE_TYPE.NOT_IN_PLACE, unsorted.clone());
228231
if (checkResults && !check(result))
229232
System.err.println("MergeSort failed.");
230233
long aMerge = System.nanoTime();
@@ -233,11 +236,11 @@ public static void main(String[] args) {
233236
if (showResult)
234237
showResult(unsorted, result);
235238
if (showComparison)
236-
mergeResults[mergeCount++] = diff;
239+
mergeNotInPlaceResults[mergeNotInPlaceCount++] = diff;
237240
System.gc();
238241

239242
bMerge = System.nanoTime();
240-
result = MergeSort.sort(sorted.clone());
243+
result = MergeSort.sort(MergeSort.SPACE_TYPE.NOT_IN_PLACE, sorted.clone());
241244
if (checkResults && !check(result))
242245
System.err.println("MergeSort failed.");
243246
aMerge = System.nanoTime();
@@ -246,11 +249,11 @@ public static void main(String[] args) {
246249
if (showResult)
247250
showResult(sorted, result);
248251
if (showComparison)
249-
mergeResults[mergeCount++] = diff;
252+
mergeNotInPlaceResults[mergeNotInPlaceCount++] = diff;
250253
System.gc();
251254

252255
bMerge = System.nanoTime();
253-
result = MergeSort.sort(reverse.clone());
256+
result = MergeSort.sort(MergeSort.SPACE_TYPE.NOT_IN_PLACE, reverse.clone());
254257
if (checkResults && !check(result))
255258
System.err.println("MergeSort failed.");
256259
aMerge = System.nanoTime();
@@ -259,7 +262,52 @@ public static void main(String[] args) {
259262
if (showResult)
260263
showResult(reverse, result);
261264
if (showComparison)
262-
mergeResults[mergeCount++] = diff;
265+
mergeNotInPlaceResults[mergeNotInPlaceCount++] = diff;
266+
System.gc();
267+
268+
System.out.println();
269+
System.out.flush();
270+
}
271+
272+
if (showMergeInPlace) {
273+
// Merge sort
274+
long bMerge = System.nanoTime();
275+
Integer[] result = MergeSort.sort(MergeSort.SPACE_TYPE.IN_PLACE, unsorted.clone());
276+
if (checkResults && !check(result))
277+
System.err.println("MergeSort failed.");
278+
long aMerge = System.nanoTime();
279+
double diff = (aMerge - bMerge) / 1000000d / 1000d;
280+
System.out.println("Random: MergeSort=" + FORMAT.format(diff) + " secs");
281+
if (showResult)
282+
showResult(unsorted, result);
283+
if (showComparison)
284+
mergeInPlaceResults[mergeInPlaceCount++] = diff;
285+
System.gc();
286+
287+
bMerge = System.nanoTime();
288+
result = MergeSort.sort(MergeSort.SPACE_TYPE.IN_PLACE, sorted.clone());
289+
if (checkResults && !check(result))
290+
System.err.println("MergeSort failed.");
291+
aMerge = System.nanoTime();
292+
diff = (aMerge - bMerge) / 1000000d / 1000d;
293+
System.out.println("Sorted: MergeSort=" + FORMAT.format(diff) + " secs");
294+
if (showResult)
295+
showResult(sorted, result);
296+
if (showComparison)
297+
mergeInPlaceResults[mergeInPlaceCount++] = diff;
298+
System.gc();
299+
300+
bMerge = System.nanoTime();
301+
result = MergeSort.sort(MergeSort.SPACE_TYPE.IN_PLACE, reverse.clone());
302+
if (checkResults && !check(result))
303+
System.err.println("MergeSort failed.");
304+
aMerge = System.nanoTime();
305+
diff = (aMerge - bMerge) / 1000000d / 1000d;
306+
System.out.println("Reverse sorted: MergeSort=" + FORMAT.format(diff) + " secs");
307+
if (showResult)
308+
showResult(reverse, result);
309+
if (showComparison)
310+
mergeInPlaceResults[mergeInPlaceCount++] = diff;
263311
System.gc();
264312

265313
System.out.println();
@@ -593,9 +641,13 @@ private static final void showComparison() {
593641
int i = 0;
594642
System.out.println("Shell sort\t\t\t" + FORMAT.format(shellResults[i++]) + "\t" + FORMAT.format(shellResults[i++]) + "\t" + FORMAT.format(shellResults[i++]));
595643
}
596-
if (showMerge) {
644+
if (showMergeInPlace) {
645+
int i = 0;
646+
System.out.println("Merge (in-place) sort\t\t" + FORMAT.format(mergeInPlaceResults[i++]) + "\t" + FORMAT.format(mergeInPlaceResults[i++]) + "\t" + FORMAT.format(mergeInPlaceResults[i++]));
647+
}
648+
if (showMergeNotInPlace) {
597649
int i = 0;
598-
System.out.println("Merge sort\t\t\t" + FORMAT.format(mergeResults[i++]) + "\t" + FORMAT.format(mergeResults[i++]) + "\t" + FORMAT.format(mergeResults[i++]));
650+
System.out.println("Merge (not-in-place) sort\t" + FORMAT.format(mergeNotInPlaceResults[i++]) + "\t" + FORMAT.format(mergeNotInPlaceResults[i++]) + "\t" + FORMAT.format(mergeNotInPlaceResults[i++]));
599651
}
600652
if (showQuick) {
601653
int i = 0;

0 commit comments

Comments
 (0)