Skip to content

Commit 81070e4

Browse files
added quick sort algorithm
1 parent 1982bd5 commit 81070e4

File tree

4 files changed

+202
-0
lines changed

4 files changed

+202
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ gradle clean assemble
3434
- Merge Sort
3535
-- [Recursive](https://github.com/marioluan/java-sorting-algorithms/blob/master/src/main/java/io/github/marioluan/algorithms/sorting/MergeSortRecursive.java)
3636
-- [Iterative](https://github.com/marioluan/java-sorting-algorithms/blob/master/src/main/java/io/github/marioluan/algorithms/sorting/MergeSortIterative.java)
37+
- [Quick Sort](https://github.com/marioluan/java-sorting-algorithms/blob/master/src/main/java/io/github/marioluan/algorithms/sorting/QuickSort.java)
3738

3839
## References
3940
- [https://www.coursera.org/learn/algorithms-part1](https://www.coursera.org/learn/algorithms-part1)

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ repositories {
3131
}
3232

3333
dependencies {
34+
compile 'edu.princeton.cs:algs4:1.0.2'
35+
3436
testCompile 'com.greghaskins:spectrum:1.0.0'
3537
testCompile group: 'junit', name: 'junit', version: '4.12'
3638

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package io.github.marioluan.algorithms.sorting;
2+
3+
import edu.princeton.cs.algs4.StdRandom;
4+
5+
/**
6+
* Recursive in-place, non stable implementation of quick sort algorithm. <br>
7+
* <strong>Time complexity:</strong> O(N log N) <br>
8+
* <strong>Space complexity:</strong> O(??) <br>
9+
* References:
10+
* <ul>
11+
* <li><a>https://www.coursera.org/learn/algorithms-part1</a>.</li>
12+
* <li><a>https://upload.wikimedia.org/wikipedia/commons/6/6a/Sorting_quicksort_anim.gif</a></li>
13+
* </ul>
14+
*
15+
* @author marioluan
16+
*/
17+
@SuppressWarnings("rawtypes")
18+
public final class QuickSort extends Sortable {
19+
20+
private final static int CUTOFF = 10;
21+
22+
/**
23+
* Sort the array a.
24+
*
25+
* @param a
26+
* the array to be sorted
27+
*/
28+
public static void sort(Comparable[] a) {
29+
30+
/**
31+
* Preserves randomness, performance guarantees.
32+
* E.g.: If the array is already sorted, it would take ~ 1/2 N ^2 of
33+
* compares. Since we're shuffling the array, it is extremely unlike to
34+
* happen. :)
35+
* <br>
36+
* Conclusion: Best case and Average cases would happen \o/.
37+
*/
38+
StdRandom.shuffle(a);
39+
40+
sort(a, 0, a.length - 1);
41+
}
42+
43+
/**
44+
* Recursively sort the array a within a and hi bounds.
45+
*
46+
* @param a
47+
* the array to be sorted
48+
* @param lo
49+
* lower bound
50+
* @param hi
51+
* upper bound
52+
*/
53+
private static void sort(Comparable[] a, int lo, int hi) {
54+
// Improves the running time by ~ 20% for tiny subarrays.
55+
if (hi <= lo + CUTOFF - 1) {
56+
InsertionSort.sort(a, lo, hi);
57+
return;
58+
}
59+
60+
/**
61+
* TODO: compute a random medium of 3 numbers from the array a, so that
62+
* we can improve the running time of the algorithm by 10%.
63+
* E.g.:
64+
* int m = medianOf3(a, lo, lo + (hi - lo) / 2, hi);
65+
* swap(a, lo, m); // place the m into the first position of the array,
66+
* so the partition function chooses it
67+
*/
68+
int j = partition(a, lo, hi);
69+
70+
sort(a, lo, j - 1);
71+
sort(a, j + 1, hi);
72+
}
73+
74+
/**
75+
* Partition the array a within its lo and hi bounds.
76+
*
77+
* @param a
78+
* @param lo
79+
* @param hi
80+
* @return returns the index of the element in place after the partition
81+
*/
82+
protected static int partition(Comparable[] a, int lo, int hi) {
83+
int i = lo;
84+
int j = hi + 1;
85+
86+
while (true) {
87+
// move the cursor from left -> right
88+
while (less(a[++i], a[lo]))
89+
if (i == hi)
90+
break;
91+
92+
// move the cursor from right -> left
93+
while (less(a[lo], a[--j])) {
94+
// redundant, 'cause when a[lo] == a[--j], it automatically
95+
// breaks the loop :)
96+
if (j == lo)
97+
break;
98+
}
99+
100+
// stop when i and j pointers cross
101+
if (i >= j)
102+
break;
103+
104+
/**
105+
* When we got here, a[i] is greater than a[j] so we need to
106+
* exchange them, so that
107+
* all elements from left of a[lo] are lower than a[lo] and all
108+
* elements to the right of a[lo] are greater than a[lo]
109+
*/
110+
swap(a, i, j);
111+
}
112+
113+
// when pointers cross, puts the pivot element in place
114+
swap(a, lo, j);
115+
116+
// returns the index of item now known to be in place
117+
return j;
118+
}
119+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package io.github.marioluan.algorithms.sorting;
2+
3+
import static org.junit.Assert.assertArrayEquals;
4+
import static org.junit.Assert.assertNotEquals;
5+
import static org.junit.Assert.assertNull;
6+
import static com.greghaskins.spectrum.Spectrum.describe;
7+
import static com.greghaskins.spectrum.Spectrum.beforeEach;
8+
import static com.greghaskins.spectrum.Spectrum.it;
9+
10+
import java.util.Arrays;
11+
import java.util.Random;
12+
13+
import org.junit.runner.RunWith;
14+
15+
import com.greghaskins.spectrum.Spectrum;
16+
17+
import io.github.marioluan.algorithms.test.support.SupportHelper;
18+
19+
@SuppressWarnings("rawtypes")
20+
@RunWith(Spectrum.class)
21+
public class QuickSortTest {
22+
23+
private static final Random RANDOM = new Random();
24+
private Comparable[] array = null;
25+
private Comparable[] clone = null;
26+
private int n = 0;
27+
28+
{
29+
describe("MergeSortRecursive", () -> {
30+
describe(".sort", () -> {
31+
32+
describe("when array is small", () -> {
33+
beforeEach(() -> {
34+
n = RANDOM.nextInt(7) + 1;
35+
array = SupportHelper.buildRandomArray(n);
36+
clone = array.clone();
37+
});
38+
39+
it("sorts it", () -> {
40+
Arrays.sort(clone);
41+
QuickSort.sort(array);
42+
43+
assertArrayEquals(array, clone);
44+
});
45+
});
46+
47+
describe("when array is huge", () -> {
48+
beforeEach(() -> {
49+
n = RANDOM.nextInt((int) Math.pow(10, 6)) + 1;
50+
array = SupportHelper.buildRandomArray(n);
51+
clone = array.clone();
52+
});
53+
54+
it("sorts it", () -> {
55+
Arrays.sort(clone);
56+
QuickSort.sort(array);
57+
58+
assertArrayEquals(array, clone);
59+
});
60+
});
61+
62+
describe("when array is partially sorted", () -> {
63+
beforeEach(() -> {
64+
array = new Comparable[] { 1, 2, 3, 6, 9, 5, 10, 4, 11,
65+
13, 14, 15, 16, 17, 18, 19, 20 };
66+
clone = array.clone();
67+
});
68+
69+
it("sorts it", () -> {
70+
Arrays.sort(clone);
71+
QuickSort.sort(array);
72+
73+
assertArrayEquals(array, clone);
74+
});
75+
});
76+
77+
});
78+
});
79+
}
80+
}

0 commit comments

Comments
 (0)