集合的排列组合

来源:互联网 发布:矩阵制监理组织 编辑:程序博客网 时间:2024/06/05 21:32

在编程的时候有时会碰到需要得到一组集合的某种排列组合集,这里用穷举法来求解。

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,ca,b,da,c,db,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

结果看来达到预期。 

 

原创粉丝点击