Commit 8013f68e authored by Fokion Zervoudakis's avatar Fokion Zervoudakis

Add randomness to optimize performance.

parent 4a4e1795
......@@ -20,7 +20,7 @@ class AlgorithmR {
@return a random element selected uniformly from {@code A}
*/
@PseudoRandom
int pick(int[] A) {
static int pick(int[] A) {
Random R = new Random();
int n = 0;
for (int i = 0; i < A.length; i++) {
......@@ -31,17 +31,16 @@ class AlgorithmR {
return n;
}
private int rand(Random R, int min, int max) {
private static int rand(Random R, int min, int max) {
return R.nextInt((max - min) + 1) + min;
}
public static void main(String[] args) {
var max = 10000;
var A = IntStream.range(0, 10).toArray();
var R = new AlgorithmR();
var M = new HashMap<Integer, Double>();
for (var i = 0; i < max; i++) {
var n = R.pick(A);
var n = AlgorithmR.pick(A);
M.put(n, M.containsKey(n) ? M.get(n) + 1 : 1);
}
for (var E : M.entrySet()) {
......
......@@ -9,6 +9,7 @@ import java.util.stream.IntStream;
/**
{@link search.QuickSelect}
{@link sort.QuickSort}
*/
public class Knuth {
/**
......@@ -24,29 +25,28 @@ public class Knuth {
*/
@InPlace
@PseudoRandom
void shuffle(int[] A) {
public static void shuffle(int[] A) {
Random R = new Random();
for (int i = 0; i < A.length - 1; i++) {
swap(A, i, rand(R, i, A.length - 1));
}
}
private void swap(int[] A, int i, int j) {
private static void swap(int[] A, int i, int j) {
int n = A[i];
A[i] = A[j];
A[j] = n;
}
private int rand(Random R, int min, int max) {
private static int rand(Random R, int min, int max) {
return R.nextInt((max - min) + 1) + min;
}
public static void main(String[] args) {
var A = IntStream.range(0, 10).toArray();
var K = new Knuth();
for (var i = 0; i < 10; i++) {
var B = A.clone();
K.shuffle(B);
Knuth.shuffle(B);
System.out.println(Arrays.toString(B));
}
}
......
......@@ -3,10 +3,8 @@ package search;
import annotation.Bit;
import annotation.InPlace;
import annotation.pattern.DivideAndConquer;
import rand.Knuth;
/**
{@link rand.Knuth}
*/
public class QuickSelect {
/**
Asymptotic analysis:
......@@ -16,8 +14,10 @@ public class QuickSelect {
<li>time_worst=O(n^2) with sorted data and the first element as pivot
<li>space_worst=O(1)
</ul>
Based on Lomuto's partition scheme, which uses {@code x=A[r]} as pivot
<p>Based on Lomuto's partition scheme, which uses {@code x=A[r]} as pivot
element.
<p>Use the Knuth shuffle to add randomness and optimize performance (CLRS).
<p>https://algs4.cs.princeton.edu/23quicksort/
@param A the array to be searched
@param k the {@code k}th smallest element to be searched for
......@@ -28,6 +28,7 @@ public class QuickSelect {
@InPlace
@DivideAndConquer
Integer it(int[] A, int k) {
Knuth.shuffle(A);
int l = 0, r = A.length - 1;
while (r >= l) {
int m = (l + r) >>> 1;
......
......@@ -3,8 +3,9 @@ package sort;
import annotation.InPlace;
import annotation.Unstable;
import annotation.pattern.DivideAndConquer;
import rand.Knuth;
class QuickSort {
public class QuickSort {
/**
Asymptotic analysis:
<ul>
......@@ -13,8 +14,10 @@ class QuickSort {
<li>time_worst=O(n^2)
<li>space_worst=O(log n)
</ul>
Based on Lomuto's partition scheme, which uses {@code x=A[r]} as pivot
<p>Based on Lomuto's partition scheme, which uses {@code x=A[r]} as pivot
element.
<p>Use the Knuth shuffle to add randomness and optimize performance (CLRS).
<p>https://algs4.cs.princeton.edu/23quicksort/
@param A the array to be sorted
*/
......@@ -22,6 +25,7 @@ class QuickSort {
@Unstable
@DivideAndConquer
void sort(int[] A) {
Knuth.shuffle(A);
sort(A, 0, A.length - 1);
}
......
package rand;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
......@@ -8,24 +7,17 @@ import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.assertEquals;
class AlgorithmRTest {
private AlgorithmR R;
@BeforeEach
void beforeEach() {
R = new AlgorithmR();
}
@Test
void itDoesNotPickAnythingWithZeroElements() {
var A = new int[0];
R.pick(A);
AlgorithmR.pick(A);
assertEquals("[]", Arrays.toString(A));
}
@Test
void itPicksOneElement() {
var A = new int[] { 0 };
R.pick(A);
AlgorithmR.pick(A);
assertEquals("[0]", Arrays.toString(A));
}
}
package rand;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
......@@ -8,24 +7,17 @@ import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.assertEquals;
class KnuthTest {
private Knuth K;
@BeforeEach
void beforeEach() {
K = new Knuth();
}
@Test
void itDoesNotShuffleZeroElements() {
var A = new int[0];
K.shuffle(A);
Knuth.shuffle(A);
assertEquals("[]", Arrays.toString(A));
}
@Test
void itDoesNotShuffleOneElement() {
var A = new int[] { 0 };
K.shuffle(A);
Knuth.shuffle(A);
assertEquals("[0]", Arrays.toString(A));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment