上篇的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次。