Union-Find算法
目的:用于解决动态连通图的连接性问题
-
quick find
public class QuickFindUF { int[] id; int count; public QuickFindUF(int N) { count=N; id=new int[N]; for (int i = 0; i < N; i++) { id[i]=i; } } public int find(int p){ return id[p]; } public int count() { return count; } public boolean connected(int p,int q){ return find(p)==find(q); } public void union(int p,int q){ int pid=id[p]; int qid=id[q]; if(pid==qid){ return; } for (int i = 0; i < id.length; i++) { if(id[i]==pid){ id[i]=qid; } } count--; } public static void main(String[] args) { In in = new In("https://algs4.cs.princeton.edu/15uf/tinyUF.txt"); int n = in.readInt(); QuickFindUF uf = new QuickFindUF(n); while (!in.isEmpty()) { int p = in.readInt(); int q = in.readInt(); if (uf.find(p) == uf.find(q)) { continue; } uf.union(p, q); StdOut.println(p + " " + q); } StdOut.println(uf.count() + " components"); } }
find() 操作的速度显然是很快的,因为它只需要访问 id[] 数组一次。但 quick-find 算法一般无法处理大型问题,因为对于每一对输入 union() 都需要扫描整个 id[] 数组。
-
Quick-union
public class QuickUnionUF { int[] id; int count; public QuickUnionUF(int N) { count = N; id = new int[N]; for (int i = 0; i < N; i++) { id[i] = i; } } public int find(int p) { while (p != id[p]) { p = id[p]; } return p; } public int count() { return count; } public boolean connected(int p, int q) { return find(p) == find(q); } public void union(int p, int q) { int pRoot = find(p); int qRoot = find(q); if (pRoot == qRoot) { return; } id[qRoot] = pRoot; count--; } public static void main(String[] args) { In in = new In("https://algs4.cs.princeton.edu/15uf/tinyUF.txt"); int n = in.readInt(); QuickFindUF uf = new QuickFindUF(n); while (!in.isEmpty()) { int p = in.readInt(); int q = in.readInt(); if (uf.find(p) == uf.find(q)) { continue; } uf.union(p, q); StdOut.println(p + " " + q); } StdOut.println(uf.count() + " components"); } }