zoukankan      html  css  js  c++  java
  • 132.1.001 Union-Find | 并查集

    @(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

    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
    Alt text

    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

    Alt text

    3 Quick Union

    Structure-Tree

    • Check if they have the same root
      inspire: use the third standard as Reference//第三方标准作为参照物,语言同理
      Alt text

    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

    Alt text

    4 Quik-Union Improvement1 -Weighted quick-union

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

    demo
    Alt text

    improvement

    Alt text

    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


    Alt text

    5 Quik-Union Improvement2 -Path compression

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

    Alt text


    Alt text

    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

    Alt text

    7 Union-Find Application

    Alt text

    Percolation

    Alt text

    Monte Carlo simulation //蒙特卡罗模拟

    Alt text

    Dynamic connectivity solution to estimate percolation threshold

    • Clever Trick
      Alt text

    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!
    ");
    		
    		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!
    ");
    		}
    	}
    	
    	// 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
    ", "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
    ", "elapsed CPU time", elapsed);
    		StdOut.printf("%-25s= %.7f
    ", "mean", ps.mean());
    		StdOut.printf("%-25s= %.17f
    ", "stddev", ps.stddev());
    		StdOut.printf("%-25s= [%.15f, %.15f]
    ", "%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);
    	}
     
    }
    
    
  • 相关阅读:
    7、css基本选择器、层叠样式
    6、表格标签及表单标签
    5、head内常用标签
    4、body内常用符号
    3、HTML简介
    2、HTTP协议
    Mbedtls和Opesnssl 解码x509Certificate
    Django 学习5--DetailView
    Django 学习四--bootstrap
    Django 学习3--CreateView
  • 原文地址:https://www.cnblogs.com/Neo007/p/9745144.html
Copyright © 2011-2022 走看看