集合算法的回调
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, result.Length))
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);
}
}