在编程的时候有时会碰到需要得到一组集合的某种排列组合集,这里用穷举法来求解。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace PermutationCombination
{
public static class PermutationCombinationExtension
{
public static IEnumerable<IEnumerable<T>> Combination<T>(this IEnumerable<T> a, int choose)
{
int count = a.Count();
if (choose >= count)
{
yield return a;
}
else if (choose <= 1)
{
foreach (var n in (from m in a select m))
{
yield return Enumerable.Repeat(n, 1);
}
}
else
{
for (int i = 0; i + choose <= count; ++i)
{
foreach (var m in a.Skip(i + 1).Combination(choose - 1))
{
yield return a.Skip(i).Take(1).Union(m);
}
}
}
}
public static IEnumerable<T> Combination<T>(this IEnumerable<T> a, int choose, Func<T, T, T> aggregate)
{
return (from e in a.Combination(choose)
select e.Aggregate(aggregate));
}
private static IEnumerable<IEnumerable<T>> FullPermutation<T>(this IEnumerable<T> a)
{
int count = a.Count();
if (count <= 1)
{
yield return a;
}
else
{
for (int i = 0; i < count; ++i)
{
var m = a.Skip(i).Take(1);
foreach (var n in a.Except(m).FullPermutation())
{
yield return m.Union(n);
}
}
}
}
public static IEnumerable<IEnumerable<T>> Permutation<T>(this IEnumerable<T> a, int choose)
{
if (choose >= a.Count()) return a.FullPermutation();
return (from e in a.Combination(choose) select e.FullPermutation()).Aggregate((e1, e2) => e1.Union(e2));
}
public static IEnumerable<T> Permutation<T>(this IEnumerable<T> a, int choose, Func<T, T, T> aggregate)
{
return (from e in a.Permutation(choose)
select e.Aggregate(aggregate));
}
}
求组合C(Nn)穷举算法为就是先从N集合里取一个元素,然后和C(N-1,n-1)作联合,依次循环做到N,很明显这是一个递归操作,Combination的代码简单明了。
求排列P(Nn)是分2步,首先是求出C(Nn),然后是对C(Nn)的每项作全排列。而这里全排列P(NN)穷举算法则是把每一项与其差集的全排列作联合。
测试下:
var a = new[] { "a", "b", "c", "d" };
C(4, 3) -> a.Combination(3, (s1, s2) => s1 + "," + s2);
a,b,c a,b,d a,c,d b,c,d
P(4, 4) -> a.Permutation(4, (s1, s2) => s1 + "," + s2);
a,b,c,d
a,b,d,c
a,c,b,d
a,c,d,b
a,d,b,c
a,d,c,b
b,a,c,d
b,a,d,c
b,c,a,d
b,c,d,a
b,d,a,c
b,d,c,a
c,a,b,d
c,a,d,b
c,b,a,d
c,b,d,a
c,d,a,b
c,d,b,a
d,a,b,c
d,a,c,b
d,b,a,c
d,b,c,a
d,c,a,b
d,c,b,a
结果看来达到预期。