並查集資料結構的幾種實現
阿新 • • 發佈:2019-01-02
第一種實現
每一個節點都只是指向根節點
find是 常數時間複雜度的, union是 線性時間複雜度的。
class quickFind { int[] a; int count; void init (int N) { a = new int[N]; for (int i = 0; i < N; i++) { a[i] = i; } count = N; } boolean connected(int p , int q) { return find(p) == find(q); } int find (intp) { return a[p]; } void union(int p , int q) { int proot = find(p); int qroot = find(q); if (proot == qroot) { return; } for (int i = 0; i < a.length; i++) { if (a[i] == proot) { a[i] = qroot; } } count--; } }
第二種實現
每一個節點指向一個和自己在相同集合中的節點
find操作是樹的高度時間複雜度,union操作也是 樹的高度時間複雜度
class quickUnion { int[] a; int count; void init(int N) { a = new int[N]; for (int i = 0; i < N; i++) { a[i] = i; } count = N; } void find(p) { while (p != a[p]) p = a[p]; return p; }void union(int p, int q) { int proot = find(p); int qroot = find(q); if (proot == qroot) { return; } a[proot] = qroot; count--; } void connected(int p, int q) { return find(p) == find(q); } }
第三種實現其實是第二種實現的改良版本
因為第二種實現,當樹的高度比較大,趨於連結串列的時候,時間複雜度會比較高,應該儘量減小樹的高度
find時間複雜度logn,union時間複雜度logn
class quickUnion2 { int[] a; int count; int[] size; void init(int N) { a = new int[N]; size = new int[N]; for (int i = 0; i < N; i++) { a[i] = i; size[i] = 1; } count = N; } void find(p) { while (p != a[p]) p = a[p]; return p; } void union(int p, int q) { int proot = find(p); int qroot = find(q); if (proot == qroot) { return; } if (size[proot] < size[qroot]) { a[proot] = qroot; size[qroot] += size[proot]; } else { a[qroot] = proot; size[proot] += size[qroot]; } count--; } void connected(int p, int q) { return find(p) == find(q); } }
使用場景,比如 島嶼個數 問題,除了用深度優先搜尋之外,還可以用 並查集資料結構來做。