應用范圍:
一開始我有n個集合,這個集合可以先理解為數學上的集合,每個節點都首先自成一個集合,n個節點就相當于有n個集合。并查集支持的操作:你想查兩個節點是否來自同一個集合,或者想合并兩個集合
前提:
每個節點必須先自成一個集合,所有點必須建立一個集合
優點:
如果你有n個節點,你想查兩個節點是否來自于一個集合的操作數(操作發生的次數),例如你想查兩個節點是否來自于一個集合的操作次數是k,集合合并的次數為f,并且k(次數)+f(次數)是O(n),并查集的操作次數是O(n),平均查詢和合并的時間復雜度為O(1)
遞歸過程解析
image.png
代碼:
public static class Node {
// whatever you like
}
public static class DisjointSets {
public HashMap<Node, Node> fatherMap;
public HashMap<Node, Integer> rankMap;
public DisjointSets() {
fatherMap = new HashMap<Node, Node>();
rankMap = new HashMap<Node, Integer>();
}
public void makeSets(List<Node> nodes) {
fatherMap.clear();
rankMap.clear();
for (Node node : nodes) {
fatherMap.put(node, node);
rankMap.put(node, 1);
}
}
public Node findFather(Node n) {
Node father = fatherMap.get(n);
if (father != n) {
father = findFather(father);
}
fatherMap.put(n, father);
return father;
}
public void union(Node a, Node b) {
if (a == null || b == null) {
return;
}
Node aFather = findFather(a);
Node bFather = findFather(b);
if (aFather != bFather) {
int aFrank = rankMap.get(aFather);
int bFrank = rankMap.get(bFather);
if (aFrank <= bFrank) {
fatherMap.put(aFather, bFather);
rankMap.put(bFather, aFrank + bFrank);
} else {
fatherMap.put(bFather, aFather);
rankMap.put(aFather, aFrank + bFrank);
}
}
}
}