以下是一个简单的用Java实现并查集的代码:
import java.util.HashMap;
import java.util.Map;
class UnionFind {
private Map<Integer, Integer> parent;
private Map<Integer, Integer> rank;
//1.定义了一个并查集数据结构
public UnionFind() {
//1.1用于存储每个元素的父节点
parent = new HashMap<>();
//1.2用于记录树的深度(秩)
rank = new HashMap<>();
}
//2.向并查集中添加一个新的元素 x,将其父节点设为自身,并设置初始的秩为 0
public void makeSet(int x) {
parent.put(x, x);
rank.put(x, 0);
}
//3.实现查找操作,用于找到元素 x 所在的集合(即根节点),并在查找的过程中进行路径压缩,以提高后续查找效率
public int find(int x) {
if (parent.get(x) != x) {
parent.put(x, find(parent.get(x)));
}
return parent.get(x);
}
//4.合并操作,将元素 x 所在集合的根节点与元素 y 所在集合的根节点进行合并。在合并时,根据秩的大小来决定合并的方式,保持树的平衡,并更新秩的信息
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY) {
return;
}
if (rank.get(rootX) < rank.get(rootY)) {
parent.put(rootX, rootY);
} else if (rank.get(rootX) > rank.get(rootY)) {
parent.put(rootY, rootX);
} else {
parent.put(rootY, rootX);
rank.put(rootX, rank.get(rootX) + 1);
}
}
}
下面是一个业务场景的例子,假设有一个社交网络,其中的用户可以互相关注。我们需要实现一个功能,查找用户之间的关联关系。
import java.util.ArrayList;
import java.util.List;
class SocialNetwork {
private UnionFind uf;
public SocialNetwork(int size) {
uf = new UnionFind();
for (int i = 0; i < size; i++) {
uf.makeSet(i);
}
}
public void addFriendship(int userId1, int userId2) {
uf.union(userId1, userId2);
}
public boolean areFriends(int userId1, int userId2) {
return uf.find(userId1) == uf.find(userId2);
}
public List<Integer> getFriends(int userId) {
List<Integer> friends = new ArrayList<>();
int root = uf.find(userId);
for (int i = 0; i < uf.size(); i++) {
if (uf.find(i) == root) {
friends.add(i);
}
}
return friends;
}
}
在这个例子中,我们使用了并查集来维护用户之间的关联关系。每个用户被视为一个节点,初始化时每个节点都是一个独立的集合。当两个用户关注了彼此时,我们将它们所在的集合合并成一个集合。这样,我们就可以通过查找两个用户所在的集合是否相同来判断他们之间是否有关联关系。
业务场景中的示例代码中实现了添加关注关系、判断两个用户之间是否关注以及获取某个用户的所有关注者的功能。
并查集的优势主要体现在以下几个方面:
快速合并和查找:并查集的主要操作包括合并两个集合和查找某个元素所属的集合。这两个操作的时间复杂度都是接近常数级别的,具有较高的效率。
简单易用:并查集的实现非常简单,只需要几个基本的操作即可。对于一些简单的问题,可以很方便地使用并查集来解决。
节省空间:并查集的实现中只需要维护一个父节点数组和一个秩数组。父节点数组用来记录每个节点的父节点,秩数组用来表示每个节点所在集合的秩。相比其他数据结构,如树和图,使用并查集可以节省一部分空间。
可以用于处理动态连通性问题:并查集可以有效地解决动态连通性的问题,即随着时间变化,节点之间的连通关系可能发生变化的问题。并查集提供了快速的合并操作,可以在动态的连通图中快速地合并和查找节点。
总的来说,并查集是一种简单、高效的数据结构,适用于解决集合合并和查找问题,尤其在动态连通性问题中很有优势。