树算法实现c#

时间:2011-05-02 16:59:38

标签: c# algorithm tree

我有一些问题解决了一个算法,该算法用于找到所有可能的组合,其中包含来自N个不同列表的元素(其中N> = 2&& N< = 7 - >这个数字是固定的,我可以做出不同的方法每个N)。 问题如下: 我有五本词典:

IDictionary<int, MyEnum> listOne; 
IDictionary<int, MyEnum> listTwo;
IDictionary<int, MyEnum> listThree;
IDictionary<int, MyEnum> listFour;
IDictionary<int, MyEnum> listN;

enum MyEnum
    {
    MyEnumOne,
    MyEnumTwo,
    MyEnumThree,
    MyEnumFour,
    MyEnumFive,
    MyEnumOther
   }

可以有任意数量的元素(不超过100个,大多数时候它们有32到64个元素) 并且MyEnum是一个带有一些值的简单名称枚举。

对于每种可能的组合,我都有一些检查组合的方法,并检查它是否满足某些条件,如果满足,则根据组合存储一些数据。

我已经尝试过为每个列表使用foreach进行简单的嵌套迭代,正如预期的那样,需要很长时间才能运行!

任何帮助,我应该从哪里开始,我该怎么做,或者我不应该做的事情将非常受欢迎!,如果需要更多信息,请随时询问!

* *编辑: 基于如前所示的五个列表的组合将是例如:

(MyEnumOne, MyEnumOne, MyEnumFour, MyEnumFive, MyEnumTwo)

并且,由于这种组合可以出现几次(因为MyEnumOne值可以在listOne上多次等),我还必须记录这种组合发生了多少次。

2 个答案:

答案 0 :(得分:1)

您可以使用LINQ轻松解决此类问题。

var solutions = from pair1 in listOne
                where IsCandidate(pair1)
                from pair2 in listTwo
                where IsCandidate(pair1, pair2)
                from pair3 in listThree
                where IsCandidate(pair1, pair2, pair3)
                from pair4 in listFour
                where IsCandidate(pair1, pair2, pair3, pair4)
                from pair5 in listFive
                where IsCandidate(pair1, pair2, pair3, pair4, pair5)
                from pair6 in listSix
                where IsCandidate(pair1, pair2, pair3, pair4, pair5, pair6)
                from pair7 in listSeven
                where IsSolution(pair1, pair2, pair3, pair4, pair5, pair6, pair7)
                select new { pair1, pair2, pair3, pair4, pair5, pair6, pair7 };

当然这种方法只有在编译时才知道列表的数量是有效的。另一种方法是使用通用方法构建可能的组合,如Eric Lippert shows in his post

查询中的所有中间where都要尽快过滤掉无效的组合。

修改

修复了有效计算相同组合发生次数的解决方案,忽略了原始源的键。

为实现这一目标,我将对每个字典应用转换。我要将每个字典转换为一个新的字典,其中键是枚举值,值将是枚举值在原始字典中出现的次数。

IDictionary<MyEnum, int> CountOccurrences(IEnumerable<MyEnum> values)
{
    return (from e in values group e by e).ToDictionary(grp => grp.Key, grp => grp.Count());
}

var solutions = from p1 in CountOccurrences(listOne.Values)
                where IsCandidate(p1)
                from p2 in CountOccurrences(listTwo.Values)
                where IsCandidate(p1, p2)
                from p3 in CountOccurrences(listThree.Values)
                where IsCandidate(p1, p2, p3)
                from p4 in CountOccurrences(listFour.Values)
                where IsCandidate(p1, p2, p3, p4)
                from p5 in CountOccurrences(listFive.Values)
                where IsCandidate(p1, p2, p3, p4, p5)
                from p6 in CountOccurrences(listSix.Values)
                where IsCandidate(p1, p2, p3, p4, p5, p6)
                from p7 in CountOccurrences(listSeven.Values)
                where IsSolution(p1, p2, p3, p4, p5, p6, p7)
                select new {
                    E1 = p1.Key,
                    E2 = p2.Key,
                    E3 = p3.Key,
                    E4 = p4.Key,
                    E5 = p5.Key,
                    E6 = p6.Key,
                    E7 = p7.Key,
                    Times = p1.Value * p2.Value * p3.Value * p4.Value * p5.Value * p6.Value * p7.Value
                };

答案 1 :(得分:0)

通常,遇到这些问题时,您应该尝试构建解决方案,而不是盲目地浏览整个搜索空间来寻找它们。

我假设你真正需要做的是: - 你有N个列表,每个列表都有L(i)个元素。 - 你想生成长度为N的所有组合,其中第一个元素来自第一个列表,第二个元素来自第二个列表,依此类推。

似乎没有办法避免以困难的方式生成所有组合。 所有100个元素^ N~10 ^ 14 ......这将花费很多时间。

我要求小样本和需要满足的条件。