Union-Find
dynamic connectivity
Given a set of N objects.: Union command and find/connected query.
it like: connected(0,7) or union(5,0)
public class UF
UF(int N)
void union(int p, int q)
boolean connected(int p, int q)
qucik find
Data Structure:
- Integer array id[] of length N.
- Interpretation: p and q are connected iff they have the same id.
union(p ,q): change id[p] equals to id[q] .
find(p, q): just check id[p] equals to id[q] or not.
public class QuickFindUF{
private int[] id;
public QUickFindUF(int N){
id = new int[N];
for (int i =0; i < N; i++)
id[i] = i;
}
public boolean connected(int p, int q){
return id[p] == id[q];
}
public void union(int p, int q){
int pid = id[p];
int qid = id[q];
for (int i = 0; i < N; i++)
if(id[i] == pid) id[i] = qid;
}
}
But this function has some disadvantages that union is too expensive. it takes N*N array access to process a sequence of N union commands on N objects.
quick union
Data structure
- Integer array id[] of length N.
- Interpretation: id[i] is parent of i.
Find: Check if p and q have the same root.
Union: TO merge components containing p and q, set the id of p’s root to the id of q’s root.
public class QuickUNionUF{
private int[] id;
public QuickUnionUF(int N){
id = new int[N];
for (int i = 0; i < N; i++) id[i] = i;
}
public int root(int i){
while (id[i] != i) return i = id[i];
}
public boolean connected(int p, int q){
return root(p) == root(q);
}
public void union(int p, int q){
int i = root(p);
int j = root(q);
id[i] = j;
}
}
algorithm | initialize | union | find |
---|---|---|---|
quick-find | N | N | 1 |
quick-union | N | N+ | N |
树的结构让查询和合并都并得复杂,树越高,需要遍历的节点树越多. 对大图来说并不友好.
improvements
Weighted quick-union
在之前的quick-union中,都是把前一棵树加到第二课树下,如果第一颗树本身就很高,这样就会让树更高(每次连接的节点为q or p.).所以keep track of size of each tree(number of objects) and balance by linking root of smaller tree to root of larger tree.
Find: Identical to quick-union.
Union: Modify quick-union to:
-
Link root of smaller tree to root of larger tree.
-
Update the sz[] array.
-
int i = root(p); int j = root(q); if (i == j) return; if (sz[i] < sz[j]){ id[i] = j; sz[j] += sz[i]; } else{ id[j] = j; sz[i] += sz[j]; }
-
algorithm | initialize | union | connected |
---|---|---|---|
quick-find | N | N | 1 |
quick-union | N | N+ | N |
weighted QU | N | lg N+ | lg N |
another improvement: path compression