using System; namespace Rabbit.Tools { public static class SetAlgorithms { /// <summary> /// 集合算法的回调 /// </summary> /// <param name="result">运算结果</param> /// <param name="length">运算结果有效长度</param> /// <returns>控制算法是否继续,如果要结束算法,返回false</returns> /// <remarks>回调中不要修改result中的值,否则可能引起不可预知的后果</remarks> public delegate bool SetAlgorithmCallback (int[] result,int length); //argument check for arrangement and combination static bool CheckNM(int n, int m) { if (m > n || m < 0 || n < 0) throw new ArgumentException(); if (m == 0 || n == 0) return false; return true; } static bool Arrangement(int n, int rlen, int[] result, SetAlgorithmCallback callback) { if (rlen == result.Length) return callback(result, rlen); for (var i = 0; i < n; ++i) { //skip used element bool skip = false; for (var j = 0; j < rlen; ++j) { if (result[j] == i) { skip = true; break; } } if (skip) continue; //set element index result[rlen] = i; //recurrent next if (!Arrangement(n, rlen + 1, result, callback)) return false; } return true; } /// <summary> /// 求排列A(n,m) /// </summary> /// <param name="n">集合元素个数</param> /// <param name="m">取出元素个数</param> /// <param name="callback">回调</param> public static void Arrangement(int n, int m, SetAlgorithmCallback callback) { if (!CheckNM(n, m)) return; var result = new int[m]; for (var i = 0; i < n; ++i) { result[0] = i; if (!Arrangement(n, 1, result, callback)) return; } } static bool Combination(int n,int m, int i, int rlen, int[] result, SetAlgorithmCallback callback) { if (rlen == m) return callback(result, rlen); for (var j = ++i; j < n; ++j) { result[rlen] = j; if (!Combination(n,m, j, rlen + 1, result, callback)) return false; } return true; } /// <summary> /// 求组合C(n,m) /// </summary> /// <param name="n">集合元素个数</param> /// <param name="m">取出元素个数</param> /// <param name="callback">回调</param> public static void Combination(int n, int m, SetAlgorithmCallback callback) { if (!CheckNM(n, m)) return; int[] result; result = new int[n]; for (var i = 0; i < n; ++i) { result[0] = i; if (!Combination(n,m, i, 1, result,callback)) return; } } static bool SubSet(int n, int i, int rlen, int[] result, SetAlgorithmCallback callback) { if (!callback(result, rlen)) return false; if (rlen == n - 1) return true; for (var j = ++i; j < n; ++j) { result[rlen] = j; if (!SubSet(n, j, rlen + 1, result, callback)) return false; } return true; } /// <summary> /// 求除空集外包含n个元素的集合的真子集 /// </summary> /// <param name="n">集合元素个数</param> public static void SubSet(int n, SetAlgorithmCallback callback) { if (n < 0) throw new ArgumentException(); if (n == 0) return; var result = new int[n - 1]; for (var i = 0; i < n; ++i) { result[0] = i; if (!SubSet(n, i, 1, result, callback)) return; } } static bool CartesianProduct(int[] sets, int i, int[] result, SetAlgorithmCallback callback) { for (var j = 0; j < sets[i]; ++j) { result[i] = j; if (i == sets.Length - 1) { if (!callback(result, i)) return false; } else { if (!CartesianProduct(sets, i + 1, result, callback)) return false; } } return true; } /// <summary> /// 求集合笛卡尔积 /// </summary> /// <param name="sets">包含集合元素个数的数组</param> /// <param name="callback">回调函数</param> public static void CartesianProduct(int[] sets, SetAlgorithmCallback callback) { int[] result = new int[sets.Length]; CartesianProduct(sets, 0, result, callback); } } }
.Net集合算法举例
最新推荐文章于 2024-05-25 10:30:00 发布