2012-03-29 82 views
4

我有一组项目。该集合中的每个项目可以与一个或多个其他项目相关。我想建立一个算法,将直接或通过其他项目关联在一起的项目分组。算法将相关项目

实施例: 我的集合为{A,B,C,d,E,F}

a和b是相关的。 c与d有关,d与e有关。

该算法应该产生下列基团: {A,B},{C,d,E},{F}

这样做的高效算法的任何想法?在此先感谢:-)

+0

不'了'与'B',暗示有关''了'B'? – st0le 2012-03-29 04:18:38

+0

是的,它的确如此。也许我用的“关系”这个词是不够的? – 2012-03-29 04:23:54

+0

太好了。我的答案成立。 – st0le 2012-03-29 04:24:27

回答

8

使用Union Find。速度非常快。使用路径压缩,复杂度降低为O(A(N)),其中A(n)是阿克曼函数的逆。

+0

令人惊叹。不想看到这个下限的证明。 – 2012-03-29 04:53:16

+0

它确实是! :) – st0le 2012-03-29 05:28:14

+0

好吧,我读了Tarjan,马上想到了Lengauer-Tarjan算法,并且那些过去的编译器课程的所有内存都闪回了:) – 2012-03-29 08:14:32

2

要扩大st0le的回答有点...

所以,你必须元素的列表:

A,B,C,d,E,F

和联系列表:

AB
CD

初始化通过将EAC h元素在它自己的组中。

然后,遍历您关系的列表。

对于每个关系,发现每个元素是一个成员,然后团结的那些基团的基团。

所以在这个例子:

1: init -> {a}, {b}, {c}, {d}, {e}, {f} 
2: a-b -> {a,b}, {c}, {d}, {e}, {f} 
3: c-d -> {a,b}, {c,d}, {e}, {f} 
4: d-e -> {a,b}, {c,d,e}, {f} 

你会明显要检查所有的关系。取决于你如何实现'find'部分会影响算法的效率。所以你真的想知道在一组元素中找到元素的最快捷方式是什么。一种天真的方法将在O(n)中做到这一点。您可以通过保持一个记录哪个组给定的元素是在这个提高。然后,当然,当你团结两组,你将不得不更新您的记录。但这仍然有帮助,因为您可以将较小的组合并成较大的组,从而节省您需要更新的记录数量。