我阅读了the wiki page并且不明白为什么将较小的列表附加到较大的列表中会很重要。
以下是wiki页面的算法部分:
假设您有一组列表和每个列表的每个节点 包含一个对象,它所属的列表的名称,以及 该列表中的元素数量。还假设总数 所有列表中的元素都是n(即总共有n个元素)。 我们希望能够合并这些列表中的任何两个,并更新所有列表 他们的节点,以便他们仍然包含列表的名称 他们属于。合并列表A和B的规则是if A大于B然后将B的元素合并为A和 更新以前属于B的元素,反之亦然。
答案 0 :(得分:0)
这描述了一种执行更新操作的简单方法,在该方法中,您将迭代其中一个列表中的所有元素并更改标签。
迭代较短的列表会更快,因此将较小的列表合并为较大的列表是有意义的。
请注意,维基页面继续为不相交的集合数据结构描述更有效的方法,其中不再重要的是哪个列表更长。
答案 1 :(得分:0)
Union-Find只是让你保持谁是某些人的“领导者”的一种方式。
例如,假设你有5个人A,B,C,D,E。
最初每个人都在自己的集合上开始,所以你可以这样编码:
for each person in people:
dad[person] = person
通过这种方式,你可以将每个人都设置为自己的领导者。
它应该是这样的:
{A} {B} {C} {D} {E}
我们需要的第一个操作是能够找到一个集合的领导者,这个操作被称为find
。
然后我们陷入财产:领导者就是自己的父亲。
有两种可能性,或者这个人是自己的父亲,或者不是。
如果是,那么它就是该集的领导者。
如果不是,那么我们会向它的父亲询问同样的事情(如果它是它自己的父亲),所以它会发生。
你可以这样编码:
find_leader_of(person P){
if(dad[P] == P) return P
else return find_leader_of(dad[P])
}
然后我们进行union
操作,这只不过是在一组中转2个脱离集。
假设您遇到这种情况:
{A, B} {C, D} {E}
你做union(B, D)
,然后会发生什么?
首先你需要找到两组的领导者:
fst_leader = find_leader_of(B)
snd_leader = find_leader_of(D)
然后你选择这些领导者中的任何一个成为另一个的领导者:
dad[snd_leader] = fst_leader
,结果是:
union(person P1, person P2){
fst_leader = find_leader_of(P!)
snd_leader = find_leader_of(P2)
dad[snd_leader] = fst_leader
}
还有其他方法可以改进union-find和其他方法来选择谁将成为谁的领导者,但这是你必须了解的基础知识才能知道union-find的用途。
答案 2 :(得分:0)
除非您想使用天真的方法,否则您可能需要查看Hoshen-Kopelman算法https://www.ocf.berkeley.edu/~fricke/projects/hoshenkopelman/hoshenkopelman.html - 它具有N * A的摊销复杂度(其中A是逆Ackerman函数 - 其中渐近逼近常数6)。换句话说,它是WICKED FAST。
如果我没有弄错的话,很多人都在考虑坍塌树木时的整体效率 - 也就是说,这样做最有效率。我不能指出你那些研究,但我记得十年前在教科书中读过它们。
希望这有帮助。