并查集
—— 一种用于支持集合快速合并和查找操作的数据结构
1.初始化
public int[] f = new int[n];
for(int i = 0;i < n;i ++){
f[i] = i;//最开始所有的父亲节点都指向自己
}
//f[i] = 0; 或者指向0;
2.查找祖宗结点
int find(int x){
while(f[x] != x){ //沿路径查找
x = f[x];
}
return x;
}
2.路径压缩——递归式、非递归式
找到老祖宗之后,要把路径上所有的点都指向老祖宗,加快搜索速度
(1)递归压缩
int find(int x){
if(f[x] == x){
return x;
}
return f[x] = find(f[x]);
(2)非递归压缩
int find(int x) {
int j = x;
int fx = 0;
while (f[j] != j) { // 循环找到自己的老祖宗
j = f[j];
}
while (x != j) {
fx = f[x];
f[fx] = j; // 和f[x] = j 一样
x = fx;
}
return j;
}
3.集合合并
void merge(int x,int y){ //将其中一个元素祖宗的父节点指向另一个祖宗
int fx = find(x);
int fy = find(y);
if(fx!=fy){
f[fy] = fx;
}
}
4.并查集相关问题
给一个图中的n个节点, 记为 1 到 n . 在开始的时候图中没有边。
你需要完成下面两个方法:
connect(a, b), 添加连接节点 a, b 的边.
query(a, b), 检验两个节点是否联通
样例
Example 1:
Input:
ConnectingGraph(5)
query(1, 2)
connect(1, 2)
query(1, 3)
connect(2, 4)
query(1, 4)
Output:
[false,false,true]
代码:
public class ConnectingGraph {
public int[] f = null;
public int find(int x){
if(f[x] == x){
return x;
}
return f[x] = find(f[x]);
}
/*
* @param n: An integer
*/public ConnectingGraph(int n) {
// do intialization if necessary
f = new int[n+1]; // 题目要求从1-n开始
for(int i = 1;i <= n;i ++){
f[i] = i;
}
}
/*
* @param a: An integer
* @param b: An integer
* @return: nothing
*/
public void connect(int a, int b) {
// write your code here
int fa = find(a);
int fb = find(b);
if(fa!=fb){
f[fa] = fb;
}
}
/*
* @param a: An integer
* @param b: An integer
* @return: A boolean
*/
public boolean query(int a, int b) {
// write your code here
int fa = find(a);
int fb = find(b);
return fa == fb; //如果相同返回true 不同返回false
}
}