1. 程式人生 > >Algorithms,Part 1(第一週)

Algorithms,Part 1(第一週)

程式碼和筆記整理

筆記簡單整理

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的方法,估計我自己這個破筆記本有生之間系列了。