并查集1
并查集:主要用来判断两个数据是否在同一组,并能对两个不同的树进行合并成一组的一种数据结构
其实现的核心方式就是:两个在同一组的节点有着相同的祖先节点。
代码实现及解析:
1 public class UnionFind { 2 public int[] fa;//用来存储每个节点的祖先(相同组的成员具有相同的祖先) 3 public int[] rank;//用来记录当前节点所在的层级(用于优化) 4 5 public UnionFind(int n) {//将具有n个结点的并查集初始化 6 fa = new int[n]; 7 for (int i = 0; i < n; i++) { 8 this.fa[i] = i;//初始状态下并查集的祖先即为自己 9 this.rank[i] = 1;//刚开始都在第一层 10 } 11 } 12 13 public int find(int p) {//查找结点p的祖先(所在组别) 14 if (fa[p] != p) { 15 fa[p] = find(fa[p]);//直接把它的父亲调整为祖先节点 16 } 17 return fa[p]; 18 } 19 20 public boolean union(int a,int b) {//将a和b数据合并为一组 21 int rootA = find(a), rootB = find(b); 22 if (rootA == rootB) {//a,b已在同一组,无需合并 23 return false; 24 } 25 if (rank[rootA] >= rank[rootB]) {//谁在更高层就让谁做父节点 26 fa[rootB] = rootA; 27 if (rank[rootA] == rank[rootB]) { 28 rank[rootA]++;//因为A做父亲,所以要让他等级比B高 29 } 30 } 31 else { 32 fa[rootA] = rootB; 33 } 34 return true;//表示成功执行合并操作(两个数据原先不在同一组) 35 } 36 37 public boolean isSame(int a,int b) {//判断两者是否在同一个集合 38 return find(a) == find(b); 39 } 40 }
特殊结构的并查集实现(非整型数)
此处用图的点来进行举例(用于Kruskal算法)
1 public class UnionFind { 2 public HashMap<Node,Node> fatherMap;//记录边的父亲(所在分组) 3 public HashMap<Node,Integer> rankMap;//记录边所在的层级 4 5 public UnionFind(Graph g) { 6 for (Node node : g.nodeis) { 7 fatherMap.put(node, node);//一开始把自己做为祖先 8 rankMap.put(node, 1); 9 } 10 } 11 12 public Node find(Node e) { 13 if (e != fatherMap.get(e)) { 14 fatherMap.put(e, find(e)); 15 } 16 return fatherMap.get(e); 17 } 18 19 public boolean Union(Node a,Node b) { 20 Node rootA = find(a); 21 Node rootB = find(b); 22 if (rootA == rootB) { 23 return false; 24 } 25 if (rankMap.get(rootA) < rankMap.get(rootB)) { 26 fatherMap.put(a, rootB); 27 } 28 else { 29 fatherMap.put(b, rootA); 30 if (rankMap.get(rootA) == rankMap.get(rootB)) { 31 rankMap.put(rootA, rankMap.get(rootA) + 1); 32 } 33 } 34 return true; 35 } 36 37 public boolean isSame(Node a,Node b) { 38 return find(a) == find(b); 39 } 40 }