首页 > 为何我这里的IndexOutOfBoundsException无法跳过(Java)?

为何我这里的IndexOutOfBoundsException无法跳过(Java)?

这是真·CS小白在coursera Princeton Algorithms上码的第一个作业,真是好心酸...作业网址如下:
http://coursera.cs.princeton.edu/algs4/assignments/percolation.html

由两个文件组成,Percolation和PercolationStats,后者中将实例化前者并完成相应的计算和模拟。

public class Percolation {
int[][] grid;
int ranN;
int N;
WeightedQuickUnionUF wuf;

public Percolation(int N) {

    if (N <= 0) {
        throw new IllegalArgumentException("N不可以小于等于0");
    }

    grid = new int[N][N];

    for (int row = 0;row < N;row++) {
        for (int col = 0;col < N;col++){
            grid[row][col] = 0;
        }
    }

    wuf = new WeightedQuickUnionUF(N*N);

}

public void open(int i, int j) {

    if (i < 1 || i > N || j < 1 || j > N) {
        throw new IndexOutOfBoundsException("Row or Col index out of bounds!");
    }


    grid[i-1][j-1] = 1;
}

public boolean isOpen(int i, int j) {


    if (i < 1 || i > N || j < 1 || j > N) {
        throw new IndexOutOfBoundsException("Row or Col index out of bounds!");
    }

    if (grid[i-1][j-1] == 1) 
        return true;
    else 
        return false;
}

public boolean isFull(int i, int j) {

    if (i < 1 || i > N || j < 1 || j > N) {
        throw new IndexOutOfBoundsException("Row or Col index out of bounds!");
    }

    int parent = (i - 1) * N + j - 1;
    if (isOpen(i ,j) && wuf.find(parent) < N && isOpen(1, parent+1))
        return true;
    else 
        return false;
}

public boolean percolates() {
    for (int i = 1;i <= N;i++) {
        if (isFull(N, i) == true)
            return true;
    }
    return false;
}

public static void main(String[] args) {
        return;
    }
}

于是乎...为何我在PercolationStats里调用open(), isOpen()函数等,无论我的i, j是多少都会调用IndexOutOfBoundsException呢?感觉很困惑...

import java.lang.System;

public class PercolationStats {
    static int N, T;
    int rdRow, rdCol, rdN, openCount;
    double percentage;
    double[] group;
    Percolation pc;


    public PercolationStats(int N, int T) {
        int num = N * N;
        group = new double[T];
        int i = 0;

        while (i < T) {

            pc = new Percolation(N);
            openCount = 0;

            while (pc.percolates() == false) {

                do {
                    rdRow = StdRandom.uniform(1, N+1);
                    rdCol = StdRandom.uniform(1, N+1);
                }
                while (pc.isOpen(rdRow, rdCol) == false);

                pc.open(rdRow, rdCol);
                openCount++;
                rdN = (rdRow-1) * N + rdCol - 1;

                if (rdCol+1 <= N && pc.isOpen(rdRow, rdCol+1))
                    pc.wuf.union(rdN, rdN+1);
                if (rdCol-1 >= 1 && pc.isOpen(rdRow, rdCol-1))
                    pc.wuf.union(rdN, rdN-1);
                if (rdRow+1 <= N && pc.isOpen(rdRow+1, rdCol))
                    pc.wuf.union(rdN, rdN+N);
                if (rdRow-1 >= 1 && pc.isOpen(rdRow-1, rdCol))
                    pc.wuf.union(rdN, rdN-N);
        }
                percentage = openCount / num;
                group[i] = percentage;
                i++;
        }
    }

    public double mean() {
        return StdStats.mean(group);
    }

    public double stddev() {
        return StdStats.stddev(group);
    }

    public double confidenceLo() {
        double Lo = this.mean() - 1.96*this.stddev()/Math.sqrt(T);
        return Lo;
    }

    public double confidenceHi() {
        double Hi = this.mean() - 1.96*this.stddev()/Math.sqrt(T);
        return Hi;
    }

    public static void main(String[] args) {
        N = Integer.parseInt(args[0]);
        T = Integer.parseInt(args[1]);
        PercolationStats PS = new PercolationStats(N, T);
        System.out.println("mean = " + PS.mean());
        System.out.println("stddev = " + PS.stddev());
        System.out.print("95% confidence interval = " + PS.confidenceLo() + "," + PS.confidenceHi());

    }
}

下面是我调用open()所用的类。初学java,在上princeton的算法课,结果第一个作业就亚历山大...以及...我在删掉IndexOutOfBoundsException的if后,运行java PercolationStats 200 100没有任何反应啊,这是怎么回事呢?小白一枚真心求教!如果有愿意点开coursera作业并帮忙分析原因的大神本人感激不尽!谢谢~~


问题出在构造函数上,你传入了 int N 的参数, 但是没有把这个N赋给 Percolation 的变量N,所以在后续判断的时候if (i < 1 || i > N || j < 1 || j > N) 这里面N始终为0。所以总是认为数组越界。

将构造函数改成以下就可以了,只是增加了this.N = N的赋值语句。

public Percolation(int N) {

    if (N <= 0) {
        throw new IllegalArgumentException("N不可以小于等于0");
    }

    grid = new int[N][N];

    for (int row = 0;row < N;row++) {
        for (int col = 0;col < N;col++){
            grid[row][col] = 0;
        }
    }

    wuf = new WeightedQuickUnionUF(N*N);
    this.N = N;
}

然后第二个问题,我大概看了一眼。你把if语句删掉之后,下面的代码就陷入死循环了

do {
    rdRow = StdRandom.uniform(1, N+1);
    rdCol = StdRandom.uniform(1, N+1);
}
while (pc.isOpen(rdRow, rdCol) == false);

isOpen函数一直返回是true,即grid所有的元素全都是0。这也不难理解,在这一步操作之前,你只是初始化了grid矩阵,但是没有做任何赋值运算。但是你在不断的返回一个随机的rdRow和rdCol去访问这个grid的元素,所以isOpen函数始终是返回true。

so……好好debug一下你的代码……多把几步的返回结果打印出来,你就知道为啥了。


Percolation 类的N赋值了吗?似乎没有,因此你的 N被默认赋值为0
`public void open(int i, int j) {

if (i < 1 || i > N || j < 1 || j > N) {
    //i>N 一直成立 所以这个异常总是抛出
    throw new IndexOutOfBoundsException("Row or Col index out of bounds!");
}`

你可以在

public Percolation(int N){
    //在这里加个句
    this.N = N;
......
}
【热门文章】
【热门文章】