Skip to content

Commit 8c32d5e

Browse files
added quick select algorithm
1 parent 81070e4 commit 8c32d5e

File tree

4 files changed

+156
-2
lines changed

4 files changed

+156
-2
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ gradle clean assemble
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)
3737
- [Quick Sort](https://github.com/marioluan/java-sorting-algorithms/blob/master/src/main/java/io/github/marioluan/algorithms/sorting/QuickSort.java)
38+
- [Quick Select](https://github.com/marioluan/java-sorting-algorithms/blob/master/src/main/java/io/github/marioluan/algorithms/sorting/QuickSelect.java)
3839

3940
## References
4041
- [https://www.coursera.org/learn/algorithms-part1](https://www.coursera.org/learn/algorithms-part1)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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 select algorithm which
7+
* solves the select problem. <br>
8+
* <strong>Time complexity:</strong> O(N) on average <br>
9+
* <strong>Space complexity:</strong> O(??) <br>
10+
* References:
11+
* <ul>
12+
* <li><a>https://www.coursera.org/learn/algorithms-part1</a>.</li>
13+
* <li><a>https://en.wikipedia.org/wiki/Quickselect#/media/File:Selecting_quickselect_frames.gif</a></li>
14+
* </ul>
15+
*
16+
* @author marioluan
17+
*/
18+
@SuppressWarnings("rawtypes")
19+
public final class QuickSelect extends Sortable {
20+
21+
/**
22+
* Select the element on index k after sorting the array a.
23+
*
24+
* @param a
25+
* @param k
26+
* the index from a after being sorted
27+
* @return returns the value of a[k] after sort
28+
*/
29+
public static Comparable select(Comparable[] a, int k) {
30+
31+
/**
32+
* Preserves randomness, performance guarantees.
33+
* E.g.: If the array is already sorted, it would take ~ 1/2 N ^2 of
34+
* compares. Since we're shuffling the array, it is extremely unlike to
35+
* happen. :)
36+
* <br>
37+
* Conclusion: Best case and Average cases would happen \o/.
38+
*/
39+
StdRandom.shuffle(a);
40+
41+
return select(a, k, 0, a.length - 1);
42+
}
43+
44+
/**
45+
* Recursively select the element on index k of array a within lo and hi
46+
* bounds.
47+
*
48+
* @param a
49+
* @param k
50+
* @param lo
51+
* @param hi
52+
* @return returns the value of a[k] after sort
53+
*/
54+
private static Comparable select(Comparable[] a, int k, int lo, int hi) {
55+
if (hi <= lo)
56+
return a[k];
57+
58+
int j = QuickSort.partition(a, lo, hi);
59+
60+
if (j < k)
61+
lo = j + 1;
62+
else if (j > k)
63+
hi = j - 1;
64+
else
65+
return a[k];
66+
67+
return select(a, k, lo, hi);
68+
}
69+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package io.github.marioluan.algorithms.sorting;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertTrue;
5+
import static com.greghaskins.spectrum.Spectrum.describe;
6+
import static com.greghaskins.spectrum.Spectrum.beforeEach;
7+
import static com.greghaskins.spectrum.Spectrum.it;
8+
9+
import java.util.Arrays;
10+
import java.util.Random;
11+
12+
import org.junit.runner.RunWith;
13+
14+
import com.greghaskins.spectrum.Spectrum;
15+
16+
import io.github.marioluan.algorithms.test.support.SupportHelper;
17+
18+
@SuppressWarnings("rawtypes")
19+
@RunWith(Spectrum.class)
20+
public class QuiSelectTest {
21+
22+
private static final Random RANDOM = new Random();
23+
private Comparable[] array = null;
24+
private Comparable[] clone = null;
25+
private int n = 0;
26+
private int k = -1;
27+
28+
{
29+
describe("MergeSortRecursive", () -> {
30+
describe(".select", () -> {
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+
k = RANDOM.nextInt(n);
38+
});
39+
40+
it("sorts it", () -> {
41+
assertTrue(n >= 0);
42+
43+
Arrays.sort(clone);
44+
45+
assertEquals(clone[k], QuickSelect.select(array, k));
46+
});
47+
});
48+
49+
describe("when array is huge", () -> {
50+
beforeEach(() -> {
51+
n = RANDOM.nextInt((int) Math.pow(10, 6)) + 1;
52+
array = SupportHelper.buildRandomArray(n);
53+
clone = array.clone();
54+
k = RANDOM.nextInt(n);
55+
});
56+
57+
it("sorts it", () -> {
58+
assertTrue(n >= 0);
59+
60+
Arrays.sort(clone);
61+
62+
assertEquals(clone[k], QuickSelect.select(array, k));
63+
});
64+
});
65+
66+
describe("when array is partially sorted", () -> {
67+
beforeEach(() -> {
68+
array = new Comparable[] { 1, 2, 3, 6, 9, 5, 10, 4, 11,
69+
13, 14, 15, 16, 17, 18, 19, 20 };
70+
clone = array.clone();
71+
k = RANDOM.nextInt(array.length);
72+
});
73+
74+
it("sorts it", () -> {
75+
assertTrue(n >= 0);
76+
77+
Arrays.sort(clone);
78+
79+
assertEquals(clone[k], QuickSelect.select(array, k));
80+
});
81+
});
82+
83+
});
84+
});
85+
}
86+
}

src/test/java/io/github/marioluan/algorithms/sorting/QuickSortTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package io.github.marioluan.algorithms.sorting;
22

33
import static org.junit.Assert.assertArrayEquals;
4-
import static org.junit.Assert.assertNotEquals;
5-
import static org.junit.Assert.assertNull;
64
import static com.greghaskins.spectrum.Spectrum.describe;
75
import static com.greghaskins.spectrum.Spectrum.beforeEach;
86
import static com.greghaskins.spectrum.Spectrum.it;

0 commit comments

Comments
 (0)