上篇的quick-union算法的效率之因此低(平方级别),最主要的缘由是union(p,q)方法,随意将一棵树链接到另外一棵树上(一棵树对应一个连通份量)。算法
1.若是是小树(高度低)链接到大树的根节点(高度高),则小树的高度加1,而整个树的高度不变。数组
2.若是是大树(高度高)链接到小树的根节点(高度低),则大树的高度加1,而整个树的高度由原来的小树高度变成大树高度加1。app
根据quick-union算法分析,find(p)访问的数组的次数与节点p所在的高度有关。高度越高,访问数组的次数越多。ide
因而可知,为了减小访问数组的次数,提升算法效率,在执行union(p,q)操做时,确保是状况1,即小树链接到大树上。为此,须要一个数组sz[]来记录触点p所在的连通份量含有的触点(触点越多,对应的树的节点越多,即为大树)。测试
3.固然还有一种特殊状况,即p和q所在的连通份量对应的树高度相等,此时不管是p链接到q仍是q链接到p,树的高度都会增长。在加权quick-union算法中,这是最坏的状况。ui
所以,由加权quick-union构成的树的高度将远小于未加权所构造的树的高度。spa
1: public class WeightedQuickUnionUF extends QuickUnionUF {2:
3: /**4: * sz[p]表示触点p所在的连通份量所含的触点数5: */6: private int[] sz;7:
8: public WeightedQuickUnionUF(int N) {9: super(N);10: // TODO Auto-generated constructor stub11: sz = new int[N];12: for (int i = 0; i < N; i++)13: sz[i] = 1;// 初始化时,每一个触点都是一个连通份量14: }
15:
16:
17: @Override
18: public void union(int p, int q) {19: // TODO Auto-generated method stub20: int pRoot = find(p);21: int qRoot = find(q);22:
23: if(pRoot == qRoot)24: return;25:
26: if(sz[pRoot] < sz[qRoot]){//当触点p所在的连通份量对应的树是小树,则链接到q的连通份量上去27: id[pRoot] = qRoot;
28: sz[qRoot] += sz[pRoot];//不要忘了,被链接的树包含的节点数要相应的增长29: }else{//当触点p所在的连通份量对应的树是大树,则q所在的连通份量链接到p的连通份量上去30: id[qRoot] = pRoot;
31: sz[pRoot] += sz[qRoot];
32: }
33:
34: count -- ;
35: }
36:
37: public static void main(String[] args) {38: DirectInput.directInput(args);
39: int N = StdIn.readInt();40: UF uf = new WeightedQuickUnionUF(N);41: for(int i=0;i<N;i++){42: int p = StdIn.readInt();43: int q = StdIn.readInt();44:
45: if(uf.connected(p, q)) continue;46:
47: uf.union(p, q);
48: StdOut.println(p + " " + q);49: }
50: StdOut.println(uf.count() + " components");51: }
52:
53: }
测试结果code
算法分析component
1.最坏的状况:将要被归并的树的大小老是相等的(且老是2^n)。每一个树均是含有2^n节点的满二叉树,所以高度正好是n。当归并两个含有2^n节点的树时,获得含有2^(n+1)个节点的书,由此树的高度增长到n+1。由此可知,加权quick-union算法是对数级别的。即对于N个触点所构成的树最高的高度为lgN。blog
2.状况1的最坏的状况是怎么得来的?
简单的分析可知,加权quick-union算法不可能会获得线性表(未加权的quick-union会产生退化成线性表的树)。所以,每层的节点越多,树的高度就越小。最坏的状况就是满二叉树。
3.加权quick-union算法处理N个触点,M条链接时最多访问数组cMlgN次。(c为常数。每处理一条链接,调用一次union(p,q)方法。而union(p,q)是lgN级别的。lg[height(p)] + lg[height(q)] + 5 = clgN,M次即为cMlgN)。而quick-find算法以及某些状况下未加权的quick-union算法至少访问数组MN次。