union-find :用于解决触点之间的连通性问题,有一下三种算法。
/** * QuickFind 快速查找法 * 特点:能够以常数级的时间查找某一触点在哪个分量, 但是在最坏的情况下连接的花费是平凡级的。 * * 成员变量:数组arr、分量数count(数组的索引表示各个触点、数组的值表示各个触电所在的分量) * 私有方法: * 公开方法:联合 union、查找分量 find、是否联通 connection * 要求:触电不能重复,以int来表示各触点。 */ public class QuickFind { private int[] arr; public int count; public QuickFind(int n) { arr = new int[n]; for(int i=0;i<n;i++){ arr[i]=i; } this.count = n; } public void union (int p,int q){ if(connection(p,q))return; int numq = arr[q]; int nump = arr[p]; for(int i=0;i<arr.length;i++){ if(arr[i] == numq){ arr[i] = nump; } } count--; } public int find(int p){ if(p>=0&&p<arr.length) return arr[p]; return -1; } public boolean connection(int p, int q){ if(find(p)==find(q)) return true; return false; } }
/** * 快速联合方法 Quick Union * 特点:对于查找分量的花费与连接的深度有关、但是连接的花费是常数据的 * * 成员变量:数组arr、分量数count(数组的索引表示各个触点、数组的值表示各个触电与那个触点连接) * 私有方法: * 公开方法:联合 union、查找分量 find、是否联通 connection * 要求:触电不能重复,以int来表示各触点。 */ public class QuickUnion { private int[] arr; public int count; public QuickUnion(int n) { arr = new int[n]; for(int i=0;i<n;i++){ arr[i]=i; } this.count = n; } public int find(int p){ if(p>=0&&p<arr.length) { while(arr[p]!=p){ p=arr[p]; } return p; }; return -1; } public boolean connection(int p, int q){ if(find(p)==find(q)) return true; return false; } public void union (int p,int q){ if(connection(p, q)) return; //将q触点所在分量根节点连接到p所在分量,实现了将原来q触点所在分量的所有触点与q触电所在分量连接 arr[find(q)] = p; count--; } } /** * 加权快速联合方法 * 特点:是触点的平均深度减小,以减少find查询的花费 */ class WeightedQuickUnion{ private int[] arr; //加权数组,访问到根触点后,通过weight数组获取当前分量的大小 //然后将小分量连接到大分量 private int[] weight; public int count; public WeightedQuickUnion(int n) { arr = new int[n]; weight = new int [n]; for(int i=0;i<n;i++){ arr[i]=i; weight[i]=1; } this.count = n; } public int find(int p){ if(p>=0&&p<arr.length) { while(arr[p]!=p){ p=arr[p]; } return p; }; return -1; } public boolean connection(int p, int q){ if(find(p)==find(q)) return true; return false; } public void union (int p,int q){ int rootp = find(p); int rootq = find(q); if(rootp==rootq) return; if(weight[rootp]<weight[rootq]) arr[rootp]=rootq; else arr[rootq]=rootp; count--; } }
/** * 测试案例 */ public class TestCase { public static void main(String[] args) { QuickFind quickFind = new QuickFind(10); quickFind.union(4,3); quickFind.union(8,3); quickFind.union(5,6); quickFind.union(4,9); quickFind.union(2,1); quickFind.union(5,0); quickFind.union(7,2); quickFind.union(6,1); System.out.println(quickFind.count); System.out.println(quickFind.find(9)); System.out.println(quickFind.connection(4,2)); System.out.println("======================="); QuickUnion quickUnion = new QuickUnion(10); quickUnion.union(4,3); quickUnion.union(8,3); quickUnion.union(5,6); quickUnion.union(4,9); quickUnion.union(2,1); quickUnion.union(5,0); quickUnion.union(7,2); quickUnion.union(6,1); System.out.println(quickUnion.count); System.out.println(quickUnion.find(9)); System.out.println(quickUnion.connection(2,4)); System.out.println("========================="); WeightedQuickUnion weightedQuickUnion = new WeightedQuickUnion(10); weightedQuickUnion.union(4,3); weightedQuickUnion.union(8,3); weightedQuickUnion.union(5,6); weightedQuickUnion.union(4,9); weightedQuickUnion.union(2,1); weightedQuickUnion.union(5,0); weightedQuickUnion.union(7,2); weightedQuickUnion.union(6,1); System.out.println(weightedQuickUnion.count); System.out.println(weightedQuickUnion.find(9)); System.out.println(weightedQuickUnion.connection(2,4)); } } //结果 2 8 false ======================= 2 8 false ========================= 2 8 false