publicinterfaceDisjointSets{/** connects two items P and Q */voidconnect(intp,intq);/** checks to see if two items are connected */booleanisConnected(intp,intq);}
public class QuickFindDS implements DisjointSets {
private int[] id;
/* Θ(N) */
public QuickFindDS(int N){
id = new int[N];
for (int i = 0; i < N; i++){
id[i] = i;
}
}
/* need to iterate through the array => Θ(N) */
public void connect(int p, int q){
int pid = id[p];
int qid = id[q];
for (int i = 0; i < id.length; i++){
if (id[i] == pid){
id[i] = qid;
}
}
}
/* Θ(1) */
public boolean isConnected(int p, int q){
return (id[p] == id[q]);
}
}
public class QuickUnionDS implements DisjointSets {
private int[] parent;
public QuickUnionDS(int num) {
parent = new int[num];
for (int i = 0; i < num; i++) {
parent[i] = i;
}
}
private int find(int p) {
while (parent[p] >= 0) {
p = parent[p];
}
return p;
}
@Override
public void connect(int p, int q) {
int i = find(p);
int j= find(q);
parent[i] = j;
}
@Override
public boolean isConnected(int p, int q) {
return find(p) == find(q);
}
}
public class UnionFind {
private int[] parent;
private int[] size;
/**
* Creates a UnionFind data structure holding n vertices. Initially, all vertices are in disjoint sets.
*/
public UnionFind(int n) {
if (n <= 0) {
throw new IllegalArgumentException("Number of elements must be positive.");
}
parent = new int[n];
size = new int[n];
for (int i = 0;i < n; i++) {
parent[i] = i;
size[i] = 1;
}
}
/**
* Throws an exception if v1 is not a valid index.
*/
public void validate(int v1) {
if (v1 < 0 || v1 >= parent.length) {
throw new IllegalArgumentException("Index" + v1 + "is not a valid index.");
}
}
/**
* Returns the size of the set v1 belongs to.
*/
public int sizeOf(int v1) {
validate(v1);
return size[find(v1)];
}
/**
* Returns the parent of v1. If v1 is the root of a tree, returns the negative size of the tree for which v1 is the root.
*/
public int parent(int v1) {
validate(v1);
return parent[v1];
}
/**
* Returns true if nodes v1 and v2 are connected.
*/
public boolean connected(int v1, int v2) {
validate(v1);
validate(v2);
return find(v1) == find(v2);
}
/**
* Connects two elements v1 and v2 together. v1 and v2 can be any valid elements, and a union-by-size heuristic is used.
* If the sizes of the sets are equal, tie break by connecting v1’s root to v2’s root.
* Unioning a vertex with itself or vertices that are already connected should not change the sets, but it may alter the
* internal structure of the data structure.
*/
public void union(int v1, int v2) {
validate(v1);
validate(v2);
int root1 = find(v1);
int root2 = find(v2);
if (root1 == root2) return;
if (size[root1] < size[root2]) {
parent[root1] = root2;
size[root2] += size[root1];
} else {
parent[root2] = root1;
size[root1] += size[root2];
}
}
/**
* Returns the root of the set v1 belongs to. Path-compression is employed allowing for fast search-time.
*/
public int find(int v1) {
validate(v1);
if (parent[v1] != v1) {
parent[v1] = find(parent[v1]);
}
return parent[v1];
}
}