Algorithms,Part 1(第一週)
阿新 • • 發佈:2018-12-02
程式碼和筆記整理
筆記簡單整理
1.匯入jar包的操作
2.設計類先抽象功能和需要用到的變數
3.先設計測試類的介面
4.一定要討論資料結構和演算法的應用場景
5.演算法的時間複雜度需要自己跑跑試試,學會測試一切自己想測試的東西,不要迷信權威
並查集(Union-Find)
介面抽象
package unionFind;
import edu.princeton.cs.algs4.*;
public class UF {
//初始化
public UF(int n) {
// TODO 自動生成的建構函式存根
}
boolean connected (int p, int q) {
return false;
}
//合併
void union(int p ,int q) {}
public static void main(String[] args) {
//TODO 自動生成的方法存根
//輸入規模
int N = StdIn.readInt();
//初始化
UF uf = new UF(N);
//初始化一些Union
while (!StdIn.isEmpty()) {
int p = StdIn.readInt();
int q = StdIn.readInt();
if(!uf. connected(p,q)) {
uf.union(p,q);
StdOut.println(p+" "+q);
}
}
//接下來可以判斷任意兩個值是否“相連”
}
}
QuickFind實現
package unionFind;
import edu.princeton.cs.algs4.*;
public class QuickFindUF {
//id標識著他們所在的集合
private int[] id;
//初始化
public QuickFindUF(int N){
id = new int[N];
for(int i = 0 ; i < N; 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++) {
//union(q,p)指的是把所有跟p的id一樣的點的id全部改為q的id
if(id[i] == pid) {
id[i] = qid;
}
}
}
}
時間複雜度:建立O(n),判斷是否相連的connected操作為O(1),合併union操作為O(n)。
這裡假設我們在用Quick-Find方法解決動態連通性問題時最終只得到了一個連通分量,那麼我們在實際應用中至少要呼叫N-1次Union,所以顯然它對於最終只能得到少數連通分量的一般應用是O(n2)級別的。
QuickUnion實現(加權、路徑壓縮)
package unionFind;
import edu.princeton.cs.algs4.*;
public class QuickUnionUF {
//每個節點的父節點
private int[] id;
private int[] sz;
public QuickUnionUF(int N){
sz = new int[N];
id = new int[N];
for(int i = 0; i < id.length; i++) {
id[i] = i;
}
}
private int root(int i) {
while(id[i] != i) {
//路徑壓縮!!簡單的兩次尋找可以讓樹的結構更好,深度大大減少的話,是非常划算的做法。
id[i] = id[id[i]];
i = id[i];
}
return i;
}
public boolean connected(int p, int q) {
return (root(p) == root(q));
}
public void union(int p ,int q) {
int proot = root(p);
int qroot = root(q);
if(proot == qroot) {
return;
}
//加權!,永遠把小樹加在大樹上
if(sz[proot] < sz[qroot]) {
id[proot] = qroot;
sz[qroot] += sz[proot];
}else {
id[qroot] = proot;
sz[proot] += sz[qroot];
}
}
}
基礎的Quick-Union只改良了QF演算法的union操作,其union和connected操作的複雜度跟樹高有關,但是最差情況下還是N級別,還不夠,上文給出的是加權的QU演算法(加權部分已註釋),它一定有不超過log2n的樹高,其union和connected操作都具有對數級別log2n的效能。路徑壓縮後效果更佳好。
遵循前面說的測試才是真理的想法,拿我的破電腦跑了一下1百萬行的largeUF.txt(官網給的有 http://algs4.cs.princeton.edu/15uf/largeUF.txt ),還是挺慢的,吃飯期間掛著最後跑了15分鐘跑出來了。不過如果用QF的方法,估計我自己這個破筆記本有生之間系列了。