数据结构那点事-并查集
这是一个非常有趣的数据结构,但是却可以帮助解决一些复杂的问题
有四个村子(村子交通并不发达,没有歧视的意思),A村和B村之间有路,C村和D村之间有路,如果问可否从能A村去C村,答案是不能,但是如果在B村和D村之间修条路,A村便可以到达C村(A->B->D->C),今天的主角并查集就是为了解决这种相聚遥远的两个集合是否存在亲戚关系的一种数据结构
判断两个陌生人是否是亲戚很简单,顺着父母网上找,如果最后能找到一个人头上,说明是远方亲戚+.+
public class DisjointSets {
int[] pre;
public DisjointSets(int size) {
pre = new int[size];
for (int i = 0; i < size; i++) {
pre[i] = i;
}
}
void join(int x, int y) {
pre[x] = y;
}
int find(int x) {
int p = x;
while (pre[p] != p) {
p = pre[p];
}
return p;
}
public static void main(String[] args) {
DisjointSets set = new DisjointSets(4);
// 代表A->B是通的
set.join(0, 1);
// 代表D->C是通的
set.join(3, 2);
System.out.println(set.find(0) == set.find(2));// false,不通
// 从B往D修了一条路
set.join(1,3);
System.out.println(set.find(0) == set.find(2));// true,可以到达了
}
}
接下来分析一下这个数据结构帮助我们做了什么,首先pre数组代表的是一个节点的祖先或者代表节点,初始化的时候一个节点的代表节点就是他自身 ,但是AB是相通的,他们在一个集合里,因此可以用B来代表A,意识就是,能到B的地方,也可以到达A,同理能到达C的地方也能到达D,在find
函数中,不断向上查找这个元素所在集合的代表元素,在例子中找到的是A村和C村的代表,A村的代表是B,C村的代表就是C,这两个代表不同,因此走不通,但是当把B村的祖先设置为D后,B村的代表不再是B,而是要继续向上查找,最后,找到了C,这样A和C的代表就都是C了,即,两地可以互通