Steps to develop a usable algorithm using scientific method:
Define the problem.
Find an algorithm to solve it.
Fast enough?
If not, figure out why.
Find a way to address the problem.
Iterate until satisfied.
Dynamic connectivity
Given set of N objects we support two operations:
Union command, that connects two objects
Find connected objects command, that fins if two objects are connected
Another connectivity example.
Modeling the connections
Quick-Find - eager approach
The elements are connected if the have the same number in an array.
Union
In order to union (connect the points) we need to change all from id[p] to id[q].
Java implementation
Cost model: initialize O(n), union O(n), find O(1). Takes n^2 array accesses to process sequence of N union commands on N objects. It is too slow and we can't accept that, quick-find is too slow.
import java.util.Arrays;
class UF {
private int[] id;
public UF(int n) {
id = new int[n];
for (int i = 0; i < n; i++) {
id[i] = i;
}
}
@Override
public String toString() {
return Arrays.toString(id);
}
public void union(int p, int q) {
int pId = id[p];
id[p] = id[q];
for (int i = 0; i < id.length; i++) {
if (id[i] == pId) {
id[i] = id[p];
}
}
}
public boolean connected(int p, int q) {
return id[p] == id[q];
}
}
public class UnionFind {
public static void main(String[] args) {
UF uf = new UF(10);
System.out.println(uf);
uf.union(4, 3);
System.out.println(uf);
uf.union(3, 8);
System.out.println(uf);
uf.union(6, 5);
System.out.println(uf);
uf.union(9, 4);
System.out.println(uf);
uf.union(2, 1);
System.out.println(uf);
uf.union(8, 9);
System.out.println(uf);
boolean connected89 = uf.connected(8, 9);
System.out.println(connected89);
boolean connected50_1 = uf.connected(5, 0);
System.out.println(connected50_1);
uf.union(5, 0);
System.out.println(uf);
boolean connected50_2 = uf.connected(5, 0);
System.out.println(connected50_2);
boolean connected49 = uf.connected(4, 9);
System.out.println(connected49);
}
}
Insert O(n), union(log2*n) - iterative logarithm, find O(log2n). Simply said, what would take 30 years to compute, it can be done in 6 seconds when using Weighted-Path-Compressed Quick-Union.
Percolation
If we connect 1 and 2, we need to recreate groups of connected points.
We create tree structure. Before we connect two dots, we need to find root of the dot we want to connect to.Here is an example of a tree with its array.Java implementation:
Link root of smaller tree to root of larger tree.Here is the result of weighting in bigger scope.Java implementation:
As we go up through the tree, we flatten the tree by putting the node below the root.Java implementation (only this line ids[i] = ids[ids[i]]; has been added to root method).
Percolates if there is a way from to to bottom. This model is used in electricity, fluid flow, social interactions and so on. Here is how we represent the model. More about the problem to solve is here.