并查集的定义和常用的地方
并查集一般用在解决动态联通性的问题,可以用来检验给出的两个点是否属于同一个集合,也可以根据条件将两个点加入同一个集合,常见的算法问题有岛屿问题,判断网格点的联通性等。在oi-wiki上的解释更加详细,也简单易懂。
并查集的API
| public class UnionFind | 说明 |
| UnionFind(int n) | 构造函数,初始化一个含有n个量的数组 |
| int find(int p) | 找到p所属集合的标识符,中间可以使用路径压缩 |
| void union(int p, int q) | 将两个点所在集合进行合并 |
| int count() | 返回并查集中的集合数目 |
| boolean isConnected(int p, int q) | 检验两个点是否在同一个集合 |
重要函数的实现和说明
UnionFind(int n)
并查集中的私有属性一般有两个
1 private int[] record;//记录集合 2 private int count;//集合数目
构造函数写法
1 public UnionFind(int n) { 2 record = new int[n]; 3 for (int i = 0;i < n;i++) { 4 record[i] = i;//初始化时每个点所在集合的标识符都是自己 5 } 6 count = n; 7 }
int find(int p)
根据构造函数可以知道record[i]代表i所在集合标识符,record[i] = i时代表集合链接达到顶点,类似于家族中的祖先。
1 //找到p所在集合的标识符 2 public int find(int p) { 3 if (record[p] != p) record[p] = find(record[p]);//只有当record[p] = p时才说明p找到了他所在集合的标识符,否则就进行路径压缩 4 return record[p]; 5 }
void union(int p, int q)
合并两个点所在的集合,其实就是让其中一个集合的顶点链接到另一个集合的顶点。
1 //合并两个点所在集合 2 public void union(int p, int q) { 3 int pid = find(p); 4 int qid = find(q); 5 if (pid == qid) return;//p,q在同一个集合里 6 record[pid] = qid;//将p所在集合合并到q所在集合内,可以按秩合并 7 count--;//集合数减一 8 }
并查集的完整实现
1 public class UnionFind { 2 3 private int[] record; 4 private int count; 5 6 public UnionFind(int n) { 7 record = new int[n]; 8 for (int i = 0;i < n;i++) { 9 record[i] = i;//初始化时每个点所在集合的标识符都是自己 10 } 11 count = n; 12 } 13 14 //找到p所在集合的标识符 15 public int find(int p) { 16 if (record[p] != p) record[p] = find(record[p]);//只有当record[p] = p时才说明p找到了他所在集合的标识符,否则就进行路径压缩 17 return record[p]; 18 } 19 20 //合并两个点所在集合 21 public void union(int p, int q) { 22 int pid = find(p); 23 int qid = find(q); 24 if (pid == qid) return;//p,q在同一个集合里 25 record[pid] = qid;//将p所在集合合并到q所在集合内,可以按秩合并 26 count--;//集合数减一 27 } 28 29 public boolean isConnected(int p, int q) { 30 return find(p) == find(q); 31 } 32 33 public int count() { 34 return count; 35 } 36 }
浙公网安备 33010602011771号