問題描述:java
如上圖,給定一個數組,size = N ,若是 p 和 q 的 id 相等則 p 和 q 連通算法
對象連通的特性:數組
一、自反性:p 恆定連通 p 自身。測試
二、對稱性:若是 p 連通 q ,則 q 連通 p 。ui
三、傳遞性:若是 p 連通 q ,q 連通 r ,則 p 連通 r 。code
這裏簡單運用對數組 id[] 的訪問(讀或寫)次數去考慮採用 quick-find 算法的時間複雜度。對象
算法類源碼:blog
public class QuickFindUF { private int[] id; public QuickFindUF(int size) { id = new int[size]; for (int i = 0; i < size; i++) { id[i] = i; } } public boolean connected(int p, int q) { return id[p] == id[q]; } public void union(int p, int q) { int pid = id[p]; int qid = id[q]; for (int i = 0; i < id.length; i++) { if (id[i] == pid) { id[i] = qid; } } } public String toString() { //這裏爲了方便觀看數組的變化,我重寫了 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 TestQuickFind { public static void main(String[] args) { QuickFindUF qf = new QuickFindUF(10); //訪問(讀或寫)id[] 10次(N) qf.union(5, 0); //訪問id[] 10 + 2 次 System.out.println(qf); //結果:[0, 1, 2, 3, 4, 0, 6, 7, 8, 9] qf.union(6, 5); //訪問id[] 10 + 2 次 System.out.println(qf); //結果:[0, 1, 2, 3, 4, 0, 0, 7, 8, 9] //到此已鏈接了0, 5, 6三個整數(對象),總共訪問id[](2 + 1) * (10 + 2)次(3N) //若鏈接0, 5, 6, 9四個整數(對象),以下: qf.union(9, 6); //訪問id[] 10 + 2 次 //總共是(3 + 1) * (10 + 2) 次(4N) //因此往下推導將N個對象鏈接起來, //至少須要訪問(N - 1)*(N + 2)+ N = N * N + 2N - 2 = (N + 1)*(N + 1)- 3 次id[] System.out.println(qf.connected(6, 0)); //connected訪問id[] 2次 } }
須要注意的是:io
鏈接 N 個對象只須要 N - 1 次 union,訪問數組(N - 1)*(N + 2)次 。new QuickFindUF(N) 是訪問數組 N 次。因此二者相加,總共訪問數組:(N - 1)*(N + 2)+ N = (N + 1)*(N + 1)- 3 次
能夠看到,connected() 的時間複雜度是 O(1) ,當調用 n 次此方法,則時間複雜度爲增爲 O(n) ;union() 的時間複雜度爲 O(n) ,若調用 n 次此方法,則複雜度變爲 O(n * n) (2次方打不出來,很差意思哈)。
在 main 方法裏的測試代碼整體時間複雜度是 O(n * n) 級別的,即 quick-find 算法的查找對象並檢查兩個對象是否連通(connected())的速度是很快的(O(1) ~ O(n)),屬於線性增加;可執行 union() 時,速度不盡如人意,時間複雜度屬於冪增加,以目前計算機硬件的運算水準來看是較爲消耗運算時間的一種算法。