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);
    	}
     
    }
    
    
  • 相关阅读:
    How to function call using 'this' inside forEach loop
    jquery.validate.unobtrusive not working with dynamic injected elements
    Difference between jQuery.extend and jQuery.fn.extend?
    Methods, Computed, and Watchers in Vue.js
    Caution using watchers for objects in Vue
    How to Watch Deep Data Structures in Vue (Arrays and Objects)
    Page: DOMContentLoaded, load, beforeunload, unload
    linux bridge
    linux bridge
    EVE-NG网卡桥接
  • 原文地址:https://www.cnblogs.com/Neo007/p/9745144.html
Copyright © 2011-2022 走看看