并查集(Union-Find)是一种用来对元素进行分类与查找所在类的数据结构。
并查集主要有两个操作:
1. int find(int i):查找元素i所在的集合
2. void union(int i, int j):将元素i所在的集合和元素j所在的集合合并为一个集合
并查集最基本的思想是使用森林的数据结构来实现,在一开始所有元素都是一颗单独的树。当进行find查找操作时,返回这个元素所在树的根结点。当进行union合并操作时,将某个元素所在的树的根结点作为子结点连接到另一个元素中,这样就合并了两颗树,原来两个集合中的所有元素有了一个共同的根结点。
并查集还有两种常见的优化方法:路径压缩和按秩合并。
路径压缩
在执行find查找操作时,我们可以把此结点以及查找路径上的每个父结点都直接连接到根结点上,这样就压缩了树的深度,下次查找时可以直接以O(1)的时间复杂度执行find操作。
按秩合并
在执行union合并操作时,如果每次都将较小的树作为子树连接到另一颗较大的树上,则可以保持树的平衡,控制下次查询的耗时。秩是树的深度,可以反映树的大小,本文以秩来衡量树的大小进行合并。(如果使用了路径压缩优化,那么秩不能准确的反映树的深度,但是还是能反映树的大小,因此按秩合并优化与路径压缩优化不冲突)
java代码实现:
public class UnionFind {
private int[] parent;
private int[] rank;
public UnionFind(int n) {
parent = new int[n];
for (int i = 0; i < n; i++) parent[i] = i;
rank = new int[n];
}
public int find(int i) {
return parent[i] == i ? i : (parent[i] = find(parent[i]));
}
public void union(int i, int j) {
int ri = find(i), rj = find(j);
if (rank[ri] > rank[rj]) parent[rj] = ri;
else parent[ri] = rj;
if (rank[ri] == rank[rj] && ri != rj) rank[rj]++;
}
}
1860

被折叠的 条评论
为什么被折叠?



