【算法】乱序检查
乱序检查。通过实验检查表中的乱序代码是否能够产生预期的效果。编写一个程序
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/
源码下载链接: