亂序檢查。通過實驗檢查表中的亂序程式碼是否能夠產生預期的效果。編寫一個程式
ShuffleTest,接受命令列引數M和N,將大小為M的陣列打亂N次且在每次打亂之前都將陣列
重新初始化為a[i] = i。列印一個MxM的表格,對於所有的列j,行i表示的是i在打亂後
落到j的位置的次數。陣列中的所有元素的值都應該接近於N/M。
亂序程式碼:(StdRandom來自http://algs4.cs.princeton.edu/code/stdlib.jar)
/** * Rearrange the elements of a double array in random order. */ public static void shuffle(double[] a) { int N = a.length; for (int i = 0; i < N; i++) { int r = i + uniform(N-i); // between i and N-1 double temp = a[i]; a[i] = a[r]; a[r] = temp; } }
實驗程式碼:
package com.beyond.algs4.experiment; import com.beyond.algs4.lib.StdIn; import com.beyond.algs4.lib.StdOut; import com.beyond.algs4.lib.StdRandom; public class ShuffleTest { public static class RandomArray { private int M = 0; private int[] a = null; public int[] getA() { return a; } public void setA(int[] a) { this.a = a; } public RandomArray(int M) { this.M = M; this.a = new int[M]; for (int i = 0; i < M; i++) { a[i] = i; } } } public static class RandomChecker { private double[][] matrix = null; public double[][] getMatrix() { return matrix; } private int M = 0; private int N = 0; public RandomChecker(int M, int N) { this.M = M; this.N = N; matrix = new double[M][]; for (int i = 0; i < matrix.length; i++) { matrix[i] = new double[M]; } } public void execute() { for (int n = 0; n < this.N; n++) { RandomArray c = new RandomArray(M); int[] a = c.getA(); StdRandom.shuffle(a); for (int k = 0; k < a.length; k++) { int i = a[k]; int j = k; matrix[i][j] += 1; } } } public void print() { for (int i = 0; i < M; i++) { for (int j = 0; j < M; j++) { StdOut.print(matrix[i][j] + "\t"); } StdOut.print("\n"); } } } public static class BadRandomChecker { private double[][] matrix = null; public double[][] getMatrix() { return matrix; } private int M = 0; private int N = 0; public BadRandomChecker(int M, int N) { this.M = M; this.N = N; matrix = new double[M][]; for (int i = 0; i < matrix.length; i++) { matrix[i] = new double[M]; } } public void execute() { for (int n = 0; n < this.N; n++) { RandomArray c = new RandomArray(M); int[] a = c.getA(); shuffle(a); for (int k = 0; k < a.length; k++) { int i = a[k]; int j = k; matrix[i][j] += 1; } } } public void print() { for (int i = 0; i < M; i++) { for (int j = 0; j < M; j++) { StdOut.print(matrix[i][j] + "\t"); } StdOut.print("\n"); } } public static void shuffle(int[] a) { int N = a.length; for (int i = 0; i < N; i++) { int r = StdRandom.uniform(N-i); // between 0 and N-1 int temp = a[i]; a[i] = a[r]; a[r] = temp; } } } public static void main(String[] args) { StdOut.println("Please input M: "); int M = StdIn.readInt(); StdOut.println("Please input N: "); int N = StdIn.readInt(); StdOut.println("Random Check: "); RandomChecker rc = new RandomChecker(M, N); rc.execute(); rc.print(); StdOut.println("Bad Random: "); BadRandomChecker br = new BadRandomChecker(M, N); br.execute(); br.print(); } }
實驗結果:
Please input M:
10
Please input N:
1000
i\j | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 108 | 106 | 95 | 102 | 98 | 85 | 104 | 101 | 112 | 89 |
2 | 102 | 102 | 96 | 99 | 113 | 84 | 88 | 105 | 102 | 109 |
3 | 101 | 99 | 84 | 92 | 103 | 104 | 96 | 118 | 100 | 103 |
4 | 107 | 104 | 112 | 88 | 96 | 104 | 101 | 98 | 84 | 106 |
5 | 76 | 104 | 111 | 102 | 97 | 113 | 101 | 93 | 110 | 93 |
6 | 107 | 103 | 91 | 121 | 96 | 123 | 86 | 103 | 87 | 83 |
7 | 98 | 103 | 94 | 98 | 94 | 109 | 116 | 89 | 98 | 101 |
8 | 97 | 79 | 91 | 102 | 94 | 97 | 105 | 99 | 107 | 129 |
9 | 98 | 104 | 102 | 116 | 93 | 107 | 105 | 97 | 90 | 88 |
10 | 106 | 96 | 124 | 80 | 116 | 74 | 98 | 97 | 110 | 99 |
Please input M:
5
Please input N:
100
i\j | 1 | 2 | 3 | 4 | 5 |
1 | 13 | 17 | 22 | 20 | 28 |
2 | 27 | 15 | 25 | 19 | 14 |
3 | 15 | 23 | 22 | 23 | 17 |
4 | 19 | 26 | 18 | 17 | 20 |
5 | 26 | 19 | 13 | 21 | 21 |
結果分析:
當M<N時,陣列中的所有元素的值都應該接近於N/M。但當M>N時,無法得出結論。
糟糕的打亂。假設在我們的亂序程式碼中你選擇的是一個0到N-1而非i到N-1之間的隨機整數。
證明得到的結果並非均勻的分佈在N!種可能性之間。用亂序檢查的測試檢驗這個版本。
實驗結果:
Please input M:
10
Please input N:
1000
i\j | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
1 | 95 | 101 | 131 | 89 | 103 | 83 | 114 | 96 | 93 | 95 |
2 | 0 | 107 | 112 | 100 | 116 | 128 | 118 | 111 | 100 | 108 |
3 | 0 | 62 | 98 | 119 | 134 | 118 | 146 | 136 | 132 | 55 |
4 | 0 | 54 | 100 | 118 | 136 | 180 | 136 | 139 | 95 | 42 |
5 | 0 | 47 | 82 | 154 | 146 | 188 | 187 | 97 | 72 | 27 |
6 | 0 | 32 | 75 | 161 | 228 | 110 | 147 | 136 | 64 | 47 |
7 | 0 | 54 | 139 | 213 | 43 | 77 | 60 | 211 | 151 | 52 |
8 | 0 | 148 | 252 | 23 | 48 | 66 | 50 | 23 | 260 | 130 |
9 | 0 | 395 | 6 | 15 | 32 | 33 | 31 | 38 | 17 | 433 |
10 | 905 | 0 | 5 | 8 | 14 | 17 | 11 | 13 | 16 | 11 |
Please input M:
5
Please input N:
100
i\j | 1 | 2 | 3 | 4 | 5 |
1 | 18 | 18 | 23 | 17 | 24 |
2 | 0 | 22 | 29 | 32 | 17 |
3 | 0 | 15 | 31 | 40 | 14 |
4 | 0 | 44 | 10 | 8 | 38 |
5 | 82 | 1 | 7 | 3 | 7 |
參考資料:
演算法 第四版 謝路雲 譯 Algorithms Fourth Edition [美] Robert Sedgewick, Kevin Wayne著
http://algs4.cs.princeton.edu/home/
原始碼下載連結: