Percolation

Percolation

Percolation.java

主要问题为backwash。其形成原因为:因为存在上下两个虚拟节点,当percolates()为true上下贯通时,所有在最底排的已经打开的节点都会变成与上虚拟节点连通(每打开一个底部节点,都会将其与下虚拟节点连通)。解决方法是再设置一个union-find,但只提供上虚拟节点,将isFull()放在第二个union-find中进行判断。

为了方便处理,将二维数组坐标转化为一维数组坐标进行处理。

import edu.princeton.cs.algs4.WeightedQuickUnionUF;

public class Percolation {
    private int count;          				// number of open sites
    private boolean[] isOpenSite;
    private final int n;
    private final int vTop;           			// the virtual top node
    private final int vBottom;       			// the virtual bottom node
    private final WeightedQuickUnionUF uf;
    private final WeightedQuickUnionUF ufBW;    // to avoid backwash

    public Percolation(int n) {
        if (n <= 0) {
            throw new IllegalArgumentException();
        }
        count = 0;
        this.n = n;
        vTop = 0;
        vBottom = n * n + 1;
        isOpenSite = new boolean[n * n + 2];
        uf = new WeightedQuickUnionUF(n * n + 2);
        ufBW = new WeightedQuickUnionUF(n * n + 2);
        isOpenSite[vTop] = true;
        isOpenSite[vBottom] = true;
    }


    public boolean isOpen(int row, int col) {
        check(row, col);
        return isOpenSite[toIndex(row, col)];
    }

    public boolean isFull(int row, int col) {
        check(row, col);
        return ufBW.connected(vTop, toIndex(row, col));
    }

    public boolean percolates() {
        return uf.connected(vTop, vBottom);
    }

    public int numberOfOpenSites() {
        return count;
    }

    public void open(int row, int col) {
        check(row, col);
        int index = toIndex(row, col);
        if (isOpenSite[index]) {
            return;
        }

        isOpenSite[index] = true;
        // connect the node in the first row with the virtual top node
        if (row == 1) {
            uf.union(index, vTop);
            ufBW.union(index, vTop);
        }
        // connect the node in the last row with the virtual bottom node
        if (row == n) {
            uf.union(index, vBottom);
        }
        // union up
        if (row >= 2 && isOpenSite[index - n]) {
            uf.union(index, index - n);
            ufBW.union(index, index - n);
        }
        // union down
        if (row < n && isOpenSite[index + n]) {
            uf.union(index, index + n);
            ufBW.union(index, index + n);
        }
        // union left
        if (col >= 2 && isOpenSite[index - 1]) {
            uf.union(index, index - 1);
            ufBW.union(index, index - 1);
        }
        // union right
        if (col < n && isOpenSite[index + 1]) {
            uf.union(index, index + 1);
            ufBW.union(index, index + 1);

        }
        count++;
    }

    // change coordinate to index
    private int toIndex(int i, int j) {
        return (i - 1) * n + j;
    }

    // check if the coordinate is valid
    private void check(int row, int col) {
        if (row < 1 || row > n || col < 1 || col > n) {
            throw new IllegalArgumentException();
        }
    }
}

PercolationStats.java

注意需要使用指定的API:StdStats-计算平均值和方差 StdRandom-生成随机数

import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdRandom;
import edu.princeton.cs.algs4.StdStats;

public class PercolationStats {
    private static final double CONFIDENCE = 1.96;
    private final int n;
    private final int trials;
    private double[] result;       // record the fraction of open sites in each trial
    private double mean;
    private double stddev;
    private double confidenceLo;
    private double confidenceHi;

    public PercolationStats(int n, int trials) {
        if (n <= 0 || trials <= 0) {
            throw new IllegalArgumentException();
        }
        this.n = n;
        this.trials = trials;
        result = new double[trials];
        this.run();					// calculate things needed after creating object
    }

    public double mean() {
        return mean;
    }

    public double stddev() {
        return stddev;
    }

    public double confidenceLo() {
        return confidenceLo;
    }

    public double confidenceHi() {
        return confidenceHi;
    }

    private void run() {
        // calculate mean
        for (int i = 0; i < trials; i++) {
            result[i] = 1.0 * calOnce() / n / n;
        }
        mean = StdStats.mean(result);

        // calculate stddev
        stddev = StdStats.stddev(result);

        // calculate Lo and Hi
        double deviation = CONFIDENCE * stddev() / Math.sqrt(trials);
        confidenceLo = mean() - deviation;
        confidenceHi = mean() + deviation;
    }

    // calulate the number of open sites when the system percolates in one trial
    private int calOnce() {
        Percolation p = new Percolation(n);
        while (true) {
            int x = StdRandom.uniform(n) + 1;
            int y = StdRandom.uniform(n) + 1;
            // each site can be opened only once
            if (p.isOpen(x, y)) {
                continue;
            }
            p.open(x, y);
            if (p.percolates()) {
                break;
            }
        }
        return p.numberOfOpenSites();
    }

    public static void main(String[] args) {
        int n = Integer.parseInt(args[0]);
        int trials = Integer.parseInt(args[1]);
        PercolationStats ps = new PercolationStats(n, trials);
        StdOut.println("mean                    = " + ps.mean);
        StdOut.println("stddev                  = " + ps.stddev);
        StdOut.println("95% confidence interval = [" + ps.confidenceLo + ", " + ps.confidenceHi + "]");
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值