代码改变世界

动态连通性问题

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------