除了使用路径压缩这种优化措施,还可以使用按秩合并。
按秩合并(Union by Rank): 在树中进行合并操作时,总是将秩(树的高度)较小的树连接到秩较大的树的根上,这样可以保证树的深度尽可能小,从而提高查询效率。
以下是另一种并查集的一个简单实现示例:
public class UnionFind {
private int[] parent; // 记录每个节点的父节点
private int[] rank; // 记录每个节点的高度(父节点的数目)
public UnionFind(int size) {
parent = new int[size];
rank = new int[size];
for (int i = 0; i < size; i++) {
parent[i] = i; // 初始时每个节点的父节点是自己
rank[i] = 0; // 初始时每个节点的高度为0
}
}
public int find(int x) {
if (parent[x] != x) {
parent[x] = find(parent[x]); // 路径压缩
}
return parent[x];
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX != rootY) {
// 如果两个根节点的高度不同,将较低的树合并到较高的树下
if (rank[rootX] > rank[rootY]) {
parent[rootY] = rootX;
} else if (rank[rootX] < rank[rootY]) {
parent[rootX] = rootY;
} else {
// 如果两个树的高度相同,将其中一个的根节点作为另一个的子节点,并提升其高度
parent[rootY] = rootX;
rank[rootX] += 1;
}
}
}
public boolean isConnected(int x, int y) {
return find(x) == find(y);
}
}
使用:
UnionFind uf = new UnionFind(10); // 初始化并查集,有10个元素
uf.union(1, 2); // 合并元素1和元素2所在的集合
uf.union(2, 3); // 合并元素2和元素3所在的集合,此时元素1和元素3也在同一个集合中
boolean connected = uf.isConnected(1, 3); // 查询元素1和元素3是否连通
这个实现支持路径压缩,即在find
操作中通过递归查找时将路径上的每个节点直接连接到根节点,以减少查找时间。
同时,它也支持高度平衡的合并策略,即合并两个高度相同的子树时,将较低的子树连接到较高的子树上,并可能增加较高子树的高度。