查了很多资料,介绍的不太清楚。发个自己的版本。
import edu.princeton.cs.algs4.WeightedQuickUnionUF;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.StdIn;
public class Percolation
{
private boolean[] status; // 保存开关状态。
private final int gridLength;
private final int virTop; // 2个虚拟点。 方便判断是否渗透。
private final int virButton;
private final WeightedQuickUnionUF wuf;
private int number;
public Percolation(int n)
{
gridLength = n;
status = new boolean[n*n + 1]; // 第 0 个 索引 放弃不用,从 1 开始。所以 + 1.
wuf = new WeightedQuickUnionUF(n*n + 2); // 增加 2 个 虚拟点. 所以要 + 2 个位置
virButton = n*n + 1; // 底部虚拟点放置在最后一位
virTop = 0; // 顶部虚拟点用第一个位置。
}
private int Real_Index(int row,int col) { return (row - 1)*gridLength + col;}// 二维转 一维索引。从1开始,col不需要减1.
private void Check(int row,int col) // 检查坐标的有效性。
{
if(row < 1 || row > gridLength) throw new IllegalArgumentException("row must be positive");
if(col < 1 || col > gridLength) throw new IllegalArgumentException("col must be positive");
}
public void open(int row,int col)
{
Check(row,col); // 先检查 坐标是否有效。
int index = Real_Index(row,col);
status[index] = true; // 打开此位置
number++;
int neiberhood; // 开始检查上下左右的邻居 判断是否可以union
if(row == 1) wuf.union(Real_Index(row,col),virTop); // 当方块在第一行时, 将其与上方的虚拟点union.
if(row == gridLength) wuf.union(Real_Index(row,col),virButton); // 当方块在最后一行时, 与下方的虚拟点union。
if(row > 1){
Check(row-1,col); //下
neiberhood = Real_Index(row-1,col);
if(status[neiberhood]) wuf.union(neiberhood,index);
}
if(row < gridLength){
Check(row+1,col); // 上
neiberhood = Real_Index(row+1,col);
if(status[neiberhood]) wuf.union(neiberhood,index);
}
if(col > 1){
Check(row,col-1); // 左
neiberhood = Real_Index(row,col-1);
if(status[neiberhood]) wuf.union(neiberhood,index);
}
if(col < gridLength){
Check(row,col+1); // 右
neiberhood = Real_Index(row,col+1);
if(status[neiberhood]) wuf.union(neiberhood,index);
}
}
public int numberOfOpenSites() {return number;}
public boolean isOpen(int row,int col){
Check(row,col);
return status[Real_Index(row,col)];
}
public boolean isFull(int row,int col){
Check(row,col);
return wuf.connected(Real_Index(row,col),virTop);
}
public boolean percolates() {return wuf.connected(virButton,virTop);} // 判断2个虚拟点是否 union.
public static void main(String[] args){
int N = StdIn.readInt();
Percolation percola = new Percolation(N);
percola.open(1,1);
percola.open(2,1);
if(percola.wuf.connected(percola.Real_Index(1,1),percola.Real_Index(2,1)))
StdOut.println("Successful!");
}
}
PercolationStats 只要按照公式就行了。
关键要理解union-find 的 应用。