普林斯顿·算法·PART I:第一章Union-Find

动态联通性问题描述:

有N个元素,开始时我们让每一个元素肚子构成一个集合。然后按一定的顺序将属于同一组中的元素合并,构成新的集合。其间要反复查询某个元素在哪个集合中。如下所示:
在这里插入图片描述

(1)Quick-Find

声明一个长度为N的数组id,数组中元素的值代表它所属组的编号。将数组中的元素初始化为每个元素的索引值,这样就表示开始时每个元素各自构成一个独立的集合。每次union(i,j)的时候就将所有组编号等于id[i]的元素的组编号变为id[j]。每次查询元素i的组编号时,返回id[i]即可。
在这里插入图片描述
时间复杂度分析:union操作的时间复杂度为O(n),find操作的时间复杂度为O(1)

(2) Quick-Union

同样是声明一个长度为N的int型数组id。但与Quick-Find方法不同的是,Quick-Union让每一个集合中的元素构成一棵树。

每一个元素对应的id存的是自己在树上的父节点。在执行union(i,j)操作时,将i元素所在树的根指向j所在元素的根。在查询元素i的id时,返回元素i所在集合的树的根节点index即可
在这里插入图片描述
在这里插入图片描述

时间复杂度分析:union操作的时间复杂度为O(n),find的时间复杂度为O(n).

(3)Weighted Quick-Union

为了防止构建树的过程中出现tall trees,我们记录每个集合的大小。每次union的时候将小集合对应树的根链接到大集合所对应树的根上。

时间复杂度分析:union操作的时间复杂度为lg(n),find操作的时间复杂度为lg(n).

(4) Path compression Quick-Union

我们将p指向root路径上的每个节点都展开指向root。
在这里插入图片描述

性能总结

在这里插入图片描述

Programming Assignment : Percolation

reference

import edu.princeton.cs.algs4.WeightedQuickUnionUF;//直接调用WeightedQuickUnion算法API
import edu.princeton.cs.algs4.StdOut;
 

public class Percolation {
    private boolean status[];
    private int size;
    private WeightedQuickUnionUF UF;
    private WeightedQuickUnionUF UFTop;
 
    private int getPosition(int row,int col){//将方格(row,col)转换成一个数字
        return (row-1)*size+col;
    }
 
    private void checkBounds(int row,int col){//判断方格是否过界
        if(row<1||col<1||row>size||col>size)
            throw new IndexOutOfBoundsException("Index out of bounds");
    }
 
    private boolean isOpen(int pos){//判断方格是否打开
        return status[pos]==true;
    }
 
    private void union(int aPos,int bPos,WeightedQuickUnionUF aUF){
        if(!aUF.connected(aPos,bPos))//若两点未连接
            aUF.union(aPos,bPos);//则直接union
    }
 
    /**
     * Instantiates a new Percolation.
     *
     * @param n the n
     */
    public Percolation(int n) {//初始化n*n个方格
        if(n<1)
            throw new IllegalArgumentException("Illegal argument");
        size=n;
 
        status = new boolean[n * n + 2];//加上虚拟方格
        for(int i=1;i<n*n+1;i++)
            status[i]=false;//n*n个方格关闭
        status[0]=status[n*n+1]=true;//虚拟方格打开
        UF=new WeightedQuickUnionUF(n*n+2);
        UFTop=new WeightedQuickUnionUF(n*n+1);
    }
 
    /**
     * Open.
     *
     * @param row the row
     * @param col the col
     */
    public void open(int row,int col) {
        checkBounds(row, col);
        if(isOpen(row,col))
            return;
 
        int nowPos=getPosition(row,col);
        int prevRowPos=getPosition(row-1,col),nextRowPos=getPosition(row+1,col),
                prevColPos=getPosition(row,col-1),nextColPos=getPosition(row,col+1);
 
        status[nowPos]=true;//将该方格打开
 
        if(row==1){//该方格位于第一行,连接顶层的虚拟方格
            union(0,nowPos,UF);
            union(0,nowPos,UFTop);
        }
        else if(isOpen(prevRowPos)){//将该方格与位于其下边的方格连接
            union(nowPos,prevRowPos,UF);
            union(nowPos,prevRowPos,UFTop);
        }
 
        if(row==size){//该方格位于最后一行,连接底层的虚拟方格
            union(size*size+1,nowPos,UF);
        }
        else if(isOpen(nextRowPos))//将该方格与位于其上边的方格连接
        {
            union(nowPos,nextRowPos,UF);
            union(nowPos, nextRowPos, UFTop);
        }
        if(col!=1&&isOpen(prevColPos)){//如果该方格未位于最左侧,则将其与左侧打开的方格连接
            union(nowPos, prevColPos, UF);
            union(nowPos, prevColPos, UFTop);
        }
        if (col!= size && isOpen(nextColPos)) {//如果该方格未位于最右侧,则将其与右侧打开的方格连接
            union(nowPos,nextColPos,UF);
            union(nowPos,nextColPos,UFTop);
        }
    }
 
    /**
     * Is full boolean.
     *
     * @param row the row
     * @param col the col
     * @return the boolean
     */
    public boolean isFull(int row,int col) {//判断该方格与顶层虚拟方格是否联通
        checkBounds(row,col);
        return UFTop.connected(0, getPosition(row, col));
    }
 
    /**
     * Is open boolean.
     *
     * @param row the row
     * @param col the col
     * @return the boolean
     */
    public boolean isOpen(int row,int col) {
        checkBounds(row,col);
        return isOpen(getPosition(row,col));
    }
 
    /**
     * Number of open sites int.
     *
     * @return the int
     */
    public int numberOfOpenSites() {
        int count=0;
        for(int i=1;i<size*size+1;i++) {
            count+=(status[i]==true?1:0);
        }
        return count;
    }
 
    /**
     * Percolates boolean.
     *
     * @return the boolean
     */
    public boolean percolates() { //判断底层虚拟方格与顶层虚拟方格是否联通
        return UF.connected(0,size*size+1);
    }
 
    /**
     * The entry point of application.
     *
     * @param args the input arguments
     */
    public static void main(String[] args) {
        StdOut.println("This is a simple check for pecolation!");
    }
}
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdStats;
import edu.princeton.cs.algs4.StdIn;
 
/**
 * Created by Administrator on 2017/3/31.
 */
 //采用蒙特卡洛算法
public class PercolationStats {
 
    private double[] attemps;
 
    /**
     * Instantiates a new Percolation stats.
     *
     * @param N      the n
     * @param trails the trails
     */
    public PercolationStats(int N, int trails) {//N为矩阵长度,trails为试验次数
        if (N <= 0 || trails <= 0) 
            throw new IllegalArgumentException("Illegal Argument!");
        attemps = new double[trails];
        for (int i = 0; i < trails; i++) {
            Percolation checkPerco = new Percolation(N);//初始化方格,全设置为关闭状态
            int step = 0;
            while (!checkPerco.percolates()) {//表示顶层节点与底层节点未联通,直到联通,统计开放状态的方格个数
                int row = StdRandom.uniform(N) + 1;
                int column = StdRandom.uniform(N) + 1;
                if (!checkPerco.isOpen(row, column)) {
                    checkPerco.open(row, column);//随机使某个方格开放
                    step++;
                }
            }
            attemps[i] = (double) step / (N * N);
        }
 
    }
 
    /**
     * The entry point of application.
     *
     * @param args the input arguments
     */
    public static void main(String[] args) {
        int N = StdIn.readInt();
        int T = StdIn.readInt();
        PercolationStats ps = new PercolationStats(N, T);
        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());
    }
 
    /**
     * Mean double.
     *
     * @return the double
     */
    public double mean() {
        return StdStats.mean(attemps);
    }
 
    /**
     * Stddev double.
     *
     * @return the double
     */
    public double stddev() {
        return StdStats.stddev(attemps);
    }
 
    /**
     * Confidence lo double.
     *
     * @return the double
     */
    public double confidenceLo() {
        return mean() - ((1.96 * stddev())) / Math.sqrt(attemps.length);
    }
 
    /**
     * Confidence hi double.
     *
     * @return the double
     */
    public double confidenceHi() {
        return mean() + ((1.96 * stddev())) / Math.sqrt(attemps.length);
    }
 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值