如何使用链接列表实施联合查找?

时间:2019-06-23 20:31:54

标签: java list union-find

我需要使用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

谢谢您的帮助!

1 个答案:

答案 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,则两个节点ba.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

}