联合查找 Java

Union Find in Java

我正在尝试实现联合查找算法。基本上,我正在努力解决的算法部分是并集部分。应该发生的是有一个数字列表(开始时所有数字都是它们在列表中的索引)并且如果两个数字恰好具有相同的值那么这意味着它们是连接的。当 union 像 Union(1,6) 这样发生时,列表将从 [0,1,2,3,4,5,6,7,8] 到 [0,6,2,3,4,5 ,6,7,8](假设数组大小为 9)。我的实现方式如下所示:

public class QuickFindUF {
    private int[] id;
    
    public QuickFindUF(int N) {
        id = new int[N];
        for (int i=0; i < N; i++) {
            id[i] = i;
        }       
    }
    
    public boolean connected(int p, int q) {
        return id[p]==id[q];
    }
    
    public void Union(int p, int q) {
        for (int i=0; i < id.length; i++) {
            if (id[i] == id[p]) {
                id[i] = id[q];
            }
        }
    }
    public void printID() {
        for (int i = 0; i < id.length; i++) {
            System.out.print(id[i]);
        }
    }
    
    
    public static void main(String[] args) {
        QuickFindUF quickfind = new QuickFindUF(9);
        quickfind.printID();
        System.out.println();
        quickfind.Union(1,6);
        quickfind.printID();
        
        
    }
}

然而,教授在复习时说这是不对的,联合函数应该如下所示:

public void Union(int p, int q) {
        int pid = id[p];
        int qid = id[q];
        for (int i=0; i < id.length; i++) {
            if (id[i] == pid) {
                id[i] = qid;
            }
        }
    }

两个版本都可以工作,并且会更改 id,使其成为 [0,6,2,3,4,5,6,7,8] 应该的样子,这让我觉得幕后有些东西使我做错的方式,但我什至不知道从哪里开始可能是什么。我是 Java 的新手,所以我猜我只是之前没有接触过它。任何帮助将不胜感激。

您的算法在逻辑上是不正确的,因为它在循环中间更改了 id[p] 的值,因此无法更新索引 p 之后出现的事件。考虑这个例子:

int[] id = { 1, 1, 1, 4, 4 };
int p = 0, q = 3;

for(int i = 0; i < id.length; i++) {
    if(id[i] == id[p]) {
        id[i] = id[q];
    }
}

System.out.println(Arrays.toString(id));

输出:

[4, 1, 1, 4, 4]

正确的输出是:

[4, 4, 4, 4, 4]