集合的排列组合

1 篇文章 0 订阅
1 篇文章 0 订阅

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

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

结果看来达到预期。 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值