132.1.001 Union-Find | 並查集

來源:互聯網
上載者:User

標籤:tis   ash   form   ast   NPU   input   make   bounds   run   

@(132 - ACM | 演算法)

Algorithm | Coursera - by Robert Sedgewick

> Tip: Focus on WHAT is really important! > Don't just copy it!> Don't look at the subtitle> Practice is the key. Just Do it!
Backup
  • Coursera - Algorithms
  • booksite

P.S. iff == if and only if

0 Introduction
  • Dynamic connectivity problem
  • union-find data type
  • quick find
  • quick union
  • improvements
    • weighted quick union
    • weighted quick union with path compression
  • applications
    • Maze Problem
1 Steps to developing a usable algorithm
  • Model the problem
  • Find a algorithm
  • Fast enough? Fits in memory?
  • if not, figure out why
  • Find a way to address the problem
  • Iterate until satisfied
2 Quick Find | 快速尋找

Structure - Linear

Java implementation

public class QuickFindUF{    private int[] id;        //constructor    public QuickFindUF(int N)    {        id = new int[N];//allocate N*int        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++)        {            if(id[i]==pid) id[i] = qid;        }    }}
Quick find is too slow

3 Quick Union

Structure-Tree

  • Check if they have the same root
    inspire: use the third standard as Reference//第三方標準作為參照物,語言同理

Java implementation

public class QuickUnionUF{    private int[] id;    //constructor —— set each element to be its own root    public QuickUnionUF(int N)    {        id = new int[N];        for (int i = 0;i < N;i++) id[i] = i;    }    //find the root by chasing parent pointers    private int root(int i)    {        while (i != 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 i = root(p);        int j = root(q);        id[i] = j;    }}
Quick Union is also too slow

4 Quik-Union Improvement1 -Weighted quick-union

smaller tree down below - small depends on the bigger( size)

demo

improvement

Java implementation

//Data Structure //maintain extra array sz[i] to count number of objects in the tree rooted at i//sz[i] = size of tree rooted i// Find - identical to quick-union//Union//Modify quick-union to://1.Link root of smaller tree to root of larger tree.//2.Update the sz[] array    int i = root(p);    int j = root(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]};
Runing time

O(N) = lg N

5 Quik-Union Improvement2 -Path compression

Flatten the tree
In practice - Keeps tree almost completely flat.

java implementation

  • Make every other node in path point to its grandparent
private int root(int i){    while(i != id[i])    {        id[i] = id[id[i]];//only one extra line of code!        i = id[i];    }    return i;}

O(N) = N+M * lgN

6 Summary for solving the dynamic connectivity problem

7 Union-Find Application

Percolation

Monte Carlo simulation //蒙特卡羅類比

Dynamic connectivity solution to estimate percolation threshold
  • Clever Trick
8 Application - Percolation | 滲濾問題

需要注意的是Timing和Backwash的問題

  • Timing:PercolationStats.java裡StdRandom.mean()和StdRandom.stddev()都只能調用一次;Percolation.java裡實現numberOfOpenSites時切記不能使用迴圈累加,定義一個私人屬性來計數即可;實現open()時相鄰的四個sites位置直接加減n或1即可。

  • Backwash:實現isFull()時需要另外執行個體化一個不包含最下端虛擬節點的WeightedQuickUnionUF,可以解決Test 13: check for backwash with predetermined sites,Test 14: check for backwash with predetermined sites that have multiple percolating paths和Test 15: call all methods in random order until all sites are open, allowing isOpen() to be called on a site more than once

三項測試無法通過的問題。Backwash問題是指因為虛擬底部結點的存在,導致底部任一結點滲漏成功的話底部所有結點都會認為滲漏成功。原因是通過底部虛擬結點形成了迴流。從而導致isFull()方法出錯。

參考連結

  • Percolation.java
import edu.princeton.cs.algs4.WeightedQuickUnionUF; public class Percolation {        private boolean[] op; // true=open while false=blocked    private int side; // number of rows or columns    private int numOp; // number of open sites    private WeightedQuickUnionUF uf;    private WeightedQuickUnionUF ufTop;     public Percolation(int n) {                if(n <= 0) throw new IllegalArgumentException("Input should be positif!\n");                this.side = n;        this.op = new boolean[n*n+2]; // with 2 virtual sites        this.uf = new WeightedQuickUnionUF(n*n+2);         this.ufTop = new WeightedQuickUnionUF(n*n+1); // with only the upper virtual site                for(int i=1; i<n*n+1; i++) op[i] = false;        op[0] = op[n*n+1] = true;        this.numOp = 0;            }        // both ROW and COL should be integer within 1~n    private void checkBounds(int row, int col){        if(row < 1 || row > this.side || col < 1 || col > this.side){            throw new IllegalArgumentException("Index out of bounds!\n");        }    }        // get position of sites in 3 arrays: op, uf.parent & uf.size    private int getPosition(int row, int col){        return (row - 1) * this.side + col;     }        private void union(int aPos, int bPos, WeightedQuickUnionUF wq){        if(!wq.connected(aPos, bPos)){            wq.union(aPos, bPos);        }    }        private boolean isOpen(int pos){        return op[pos];    }        public void open(int row, int col) {                checkBounds(row, col);          if(isOpen(row, col)) return;                int pos = getPosition(row, col);        op[pos] = true;        numOp++;                // positions of adjacent sites        int rowPrev = pos - side, rowNext = pos + side,                colPrev = pos - 1, colNext = pos + 1;                // try connect the adjacent open sites        if(row == 1){            union(0, pos, uf);            union(0, pos, ufTop);        }else if(isOpen(rowPrev)){            union(rowPrev, pos, uf);            union(rowPrev, pos, ufTop);        }                        if(row == side){            union(side * side + 1, pos, uf);        }else if(isOpen(rowNext)){            union(rowNext, pos, uf);            union(rowNext, pos, ufTop);        }                if(col != 1 && isOpen(colPrev)) {            union(colPrev, pos, uf);            union(colPrev, pos, ufTop);        }                if(col != side && isOpen(colNext)) {            union(colNext, pos, uf);            union(colNext, pos, ufTop);        }    }        public boolean isOpen(int row, int col) {        checkBounds(row, col);        return isOpen(getPosition(row, col));                        }        /**     * check for backwash with predetermined sites that have multiple percolating paths     * in this case ufTop should be used instead of uf     * @param row     * @param col     * @return     */    public boolean isFull(int row, int col) {        checkBounds(row, col);        //return uf.connected(0, getPosition(row, col)); -> didn't pass the test!         return ufTop.connected(0, getPosition(row, col));                }        // should pass the timing check    public int numberOfOpenSites(){        return this.numOp;    }        public boolean percolates(){        return uf.connected(0, side * side + 1);    } }
  • PercolationStats.java
import edu.princeton.cs.algs4.StdIn;import edu.princeton.cs.algs4.StdOut;import edu.princeton.cs.algs4.StdRandom;import edu.princeton.cs.algs4.StdStats;import edu.princeton.cs.algs4.Stopwatch; public class PercolationStats {        private double[] results; // estimated threshold for each trial    private double avg;    private double std;        public PercolationStats(int n, int trials){                if(n <= 0 || trials <= 0) throw new IllegalArgumentException();                results = new double[trials];        for(int i = 0; i < trials; i++){            int step = 0;            Percolation pr = new Percolation(n);            while(!pr.percolates()){                int row = StdRandom.uniform(n) + 1;                int col = StdRandom.uniform(n) + 1;                if(!pr.isOpen(row, col)){                    pr.open(row, col);                    step++;                }            }            results[i] = (double)step / (n * n);        }                this.avg = StdStats.mean(results);        this.std = StdStats.stddev(results);            }        public static void main(String[] args){                StdOut.printf("%-25s\n", "Please input 2 integers");        int N = StdIn.readInt();        int T = StdIn.readInt();                Stopwatch wt = new Stopwatch();                PercolationStats ps = new PercolationStats(N, T);                // elapsed CPU time in seconds        double elapsed = wt.elapsedTime();                StdOut.printf("%-25s= %.15f\n", "elapsed CPU time", elapsed);        StdOut.printf("%-25s= %.7f\n", "mean", ps.mean());        StdOut.printf("%-25s= %.17f\n", "stddev", ps.stddev());        StdOut.printf("%-25s= [%.15f, %.15f]\n", "%95 confidence interval",                 ps.confidenceLo(), ps.confidenceHi());    }        public double mean(){        return this.avg;    }        public double stddev(){        return this.std;    }        public double confidenceLo(){        return mean() - 1.96 * stddev() / Math.sqrt(results.length);    }        public double confidenceHi(){        return mean() + 1.96 * stddev() / Math.sqrt(results.length);    } }

132.1.001 Union-Find | 並查集

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.