quick-union 的思想是:若對象 p 的 root_id 和對象 q 的 root_id 相等,則認爲 p 和 q 連通。java
若要將對象 p 和對象 q 連通(已知兩對象未連通),則將 p 的 root_id 的值設爲 q 的 root_id 的值,這樣 p 和 q 各自所在的兩個樹狀結構將會合並算法
算法類源碼:數組
public class QuickUnionUF { private int[] id; //訪問id[] N 次 public QuickUnionUF(int size) { id = new int[size]; for (int i = 0; i < size; i++) { //初始化id[] id[i] = i; } } //最多訪問id[] N 次最少訪問 1 次 private int root(int i) { //追尋父節點 while (i != id[i]) { i = id[i]; } return i; } //最多訪問id[] N + N - 1 = 2N - 1 次,最少訪問 1 + 1 = 2 次 //在最少的狀況下,若只訪問id[] 2 次,兩個對象必定不是連通的 public boolean connected(int p, int q) { return root(p) == root(q); } //若p,q從未連通 //則最多訪問id[] N 次,最少訪問 2 次 public void union(int p, int q) { int i = root(p); // (N - 1) ~ 1 int j = root(q); // 1 ~ (N - 1) id[i] = j; } public String toString() { String temp = "{"; for (int i = 0; i < id.length; i++) { if (i == id.length - 1) { temp += id[i] + "}"; break; } temp += id[i] + ", "; } return temp; } }
測試類源碼:測試
public class TestQuickUnion { public static void main(String[] args) { QuickUnionUF qu = new QuickUnionUF(10); //訪問數組id[] 10 次 qu.union(4, 3); System.out.println(qu); //{0, 1, 2, 3, 3, 5, 6, 7, 8, 9} qu.union(3, 8); System.out.println(qu); //{0, 1, 2, 8, 3, 5, 6, 7, 8, 9} qu.union(6, 5); System.out.println(qu); //{0, 1, 2, 8, 3, 5, 5, 7, 8, 9} //連通 N 個對象須要訪問id[] (N - 1) * 2 ~ (N - 1) * N 次 //訪問id[]的次數隨已連通對象的數目增長而增長 //最多增量爲已連通對象的數目 //目前的這個算法的union()的時間複雜度有所改進 //但跟quick-find相比,它的connected()時間代價較大 System.out.println(qu.connected(8, 4)); //true System.out.println(qu.connected(5, 4)); //false } }
quick-union 和 quick-find 一樣慢(處理大量數據時花費的時間)。ui
quick-find 的缺點:code
一、union() 的時間代價太大(訪問 N 次數組)對象
二、多個對象連通後造成的樹狀結構是平展的,可是當須要連通的對象的個數 N 較大時,宏觀上看,這種平展的樹狀結構的延伸,整體時間代價巨大!blog
quick-union 的缺點:源碼
一、宏觀上看,多個對象連通後造成的樹狀結構可能將變得很是高大;io
二、find(connected())的時間代價很大(訪問 2 ~ 2N -1 次數組)