动态连通性问题
2013-01-30 18:08 Polarisary 阅读(567) 评论(0) 编辑 收藏 举报问题:构建一个N个数的整数列,判断两个数是否是连通的。
通过记录父节点来构建树,从而最终形成一个森林。亮点:引入连通分量大小,连接两个分类时,将小的分类连到大的分量上,减小书的高度,这样使通过父节点找其根节点的复杂度降低,从而适用于大数据量的处理!
思路:
判断两个数字是否连通:通过数组id[]记录其父节点,根节点的父节点是其本上,若两个数字的根节点是同一个,就连通。否则,不连通。
连通两个分量:将两个不连通的分量的根节点的其中一个的父指向另一个。为了使连接后的树的高度降低,需要将小树连到大树上。采用sz[]记录连通分量大小实现。连通后将大树根的分量置为两个分类之和。
1 public class WeightedQuickUnionUF { 2 private int[] id;//父链数组 3 private int[] sz;//根节点的分量大小 4 private int count;//连通分量 5 6 public WeightedQuickUnionUF(int n) { 7 this.count = n; 8 id = new int[n]; 9 sz = new int[n]; 10 for(int i=0;i<n;i++){ 11 id[i] = i; 12 sz[i] = 1; 13 } 14 } 15 16 /** 17 * 获取连通分量 18 * @return 连通分量 19 */ 20 public int getCount(){ 21 return count; 22 } 23 24 /** 25 * 判断两个点是否连通 26 * @param p 数据点 27 * @param q 数据点 28 * @return 是/否 29 */ 30 public boolean connected(int p,int q){ 31 return find(p) == find(q); 32 } 33 34 /** 35 * 获取根节点 36 * @param m 数据点 37 * @return 根节点 38 */ 39 private int find(int m){ 40 while (m!=id[m]) 41 m = id[m]; 42 return m; 43 } 44 45 /** 46 * 连接 47 * @param p 数据点 48 * @param q 数据点 49 */ 50 public void union(int p,int q){ 51 int t = find(p); 52 int s = find(q); 53 if(sz[t]<sz[s]){ 54 id[t] = s; 55 sz[s] += sz[t]; 56 } else { 57 id[s] = t; 58 sz[t] += sz[s]; 59 } 60 count--; 61 } 62 }
------End------