我需要使用Kruskal算法编写一段代码,而这又需要使用Union-Find算法。
这包括方法Make-Set(x),Find-Set(x)和Union(x,y)。 我需要使用链接列表来实现它们,但是我不确定如何从Make-Set方法开始。
Make-Set方法应创建一个集合,并将第一个元素设为键(以比较集合)。我到底如何使用链接列表声明密钥?
简而言之:如何在Java中为链接列表实现此伪代码?
Make-Set(x) x.p = x
x.rank = 0
谢谢您的帮助!
答案 0 :(得分:0)
我听说这在过去不是指“联合查找”,而是指不相交的集合。由于节点确实具有链接,所以它并不完全是链接列表,但不一定以线性方式链接起来。它更像一棵树,其中每个节点都有一个指向其父节点的指针,您可以将树向上移动到根。
我现在没有多少时间,但是这是我如何在Java中实现它的快速草图:
class Disjoint {
Disjoint next;
Disjoint findSet() {
Disjoint head = this;
if (next != null) {
head = next.findSet();
next = head;
}
return head;
}
void union(Disjoint other) {
Disjoint us = this.findSet();
Disjoint them = other.findSet();
us.next = them;
}
}
创建实例是您的任务。您所说的“查找集”(Find-Set),我称之为查找负责人或查找领导者,也许是查找身份。不过,我在这里将其称为findSet
。它沿着链条行走以找到树的根。它还执行可选操作;它会将所有链接从递归调用中撤回,以便它们都直接指向根。这是使链条较短的优化。
最后,仅通过分配一个根的next
指针指向另一根来实现联合。我不确定您对rank
的打算是什么;如果是集合的大小,则可以为此添加一个字段,并在合并两个集合时简单地求和。但是,当我希望将其初始化为0
时,可以将其初始化为1
。
如果a
,则两个节点b
和a.findSet() == b.findSet()
属于同一集合。如果需要节点携带一些数据,则使该类通用,并将数据提供给构造函数,并添加一个吸气剂:
class Disjoint<T> {
Disjoint<T> next;
T data;
public Disjoint(final T data) {
this.data = data;
}
public T getData() {
return data;
}
// rest of class identical except Disjoint replaced with Disjoint<T> everywhere
}