1. 動態連通性
引出問題:問題的輸入是一個整數對,其中每個整數都表示一個某種類型的對象,一對整數p、q可以理解爲“p q是相連的”。我們假設“相連”是一種等價關係,這也意味着它具有:
- 自反性:p和q是互連的;
- 對稱性:如果p、q是相連的,那麼p、q也是相連的;
- 傳遞性:如果p和q是相連的且q和r是相連的,那麼q和r也是相連的。
等價關係能夠將對象分爲多個等價類。在這裏,當且僅當兩個對象相連時他們才屬於同一個等價類。我們需要設計一個數據結構來保存程序已知的所有整數對的足夠多的信息,並用他們來判斷一對新對象是否是互聯的。我們將這個問題通俗的叫做動態連通性問題。以下舉一些常見的列子:
1.1 網絡
大型計算機的連接數
1.2 變量名等價性
1.3 數學集合
2 實現
2.1 quick-find算法:
public class UF {
private int[] id;
private int count;
public UF(int N) {
count = N;
id = new int[N];
for(int i = 0;i<N;i++) {
id[i] = i;
}
}
public int count() {
return this.count;
}
public boolean connected(int q,int p) {
return find(q)==find(p);
}
public int find(int q){
//return id[q];
}
public void union(int q,int p) {
// TO do
}
}
算法實現經歷了 從quick-find 到quick-union再到加權的quick-union的改進,這裏給出最終的實現算法:
public class WeightQuickUnionUF {
private int[] id;
private int[] sz;
private int count;
public WeightQuickUnionUF(int N) {
count=N;
id = new int[N];
for (int i=0;i<N ;i++) {
id[i] = i;
}
sz= new int[N];
for (int i=0;i<N;i++) {
sz[i] = i;
}
}
public int count() {
return count;
}
public boolean connected(int q,int p) {
return find(q) == find(p);
}
public int find(int q) {
while(q != id[q]) {
q = id[q];
}
return q;
}
public void union(int p,int q) {
int i = find(p);
int j = find(q);
if (i==j) return;
if (sz[i]<sz[j]) {id[i] = j;sz[j]+=sz[i];}
else {id[j]=i;sz[i]+=sz[j];}
count--;
}
}