要生成 [1..n] 的随机排列,可以使用算法 A:
注意,不能使用算法 B:
根据算法 A,我们有以下 C# 程序:
using System; using System.Collections.Generic; static class RandomPermutation { static readonly Random rand = new Random(); static readonly byte[] seq = {1, 2, 3, 4}; static readonly int len = seq.Length; static readonly int total = 24000000; static void Swap<T>(ref T a, ref T b) { T t = a; a = b; b = t; } static int ToValue(byte[] seq) { var z = 0; foreach (var i in seq) z = z * 10 + i; return z; } static int GetRandomPermutation() { var a = (byte[])seq.Clone(); for (var n = len; n > 1; n--) Swap(ref a[rand.Next(n)], ref a[n - 1]); return ToValue(a); } static void Main() { var dict = new SortedDictionary<int, int>(); for (var i = 0; i < total; i++) { var key = GetRandomPermutation(); int count; dict.TryGetValue(key, out count); dict[key] = count + 1; } foreach (var kvp in dict) Console.WriteLine("{0}: {1,7}", kvp.Key, kvp.Value); } }
这个程序的 GetRandomPermutation() 方法实现了算法 A,其余的是测试代码。
这个程序的某次运行的结果是:
1234: 999306
1243: 998918
1324: 1002026
1342: 999857
1423: 1001389
1432: 999892
2134: 1001955
2143: 999700
2314: 999546
2341: 999570
2413: 998781
2431: 999752
3124: 1001541
3142: 999276
3214: 1000892
3241: 1000928
3412: 1001220
3421: 998861
4123: 1000518
4132: 1000431
4213: 1000458
4231: 997699
4312: 997567
4321: 999917
如果把上述程序的 GetRandomPermutation() 方法中的 rand.Next(n) 改为 rand.Next(n-1),则该程序实现了算法 B,某次运行的结果如下所示:
2341: 4001963
2413: 4003021
3142: 3997535
3421: 3998602
4123: 4000183
4312: 3998696
可见,算法 B 没有生成随机排列。从上述运行结果可以看出,生成的排列的第 k 位决不会出现 k。