簡體   English   中英

在Java中檢查二維數組中鄰居的更有效方法

[英]More efficient way to check neighbours in a two-dimensional array in Java

嘿,對於我的一些大學作業,我發現需要檢查二維數組(網格)中的相鄰單元格。 我使用的解決方案有點使用異常,但是我正在尋找一種方法來清理它,而無需像某些同學一樣加載if語句。 我當前的解決方案是

for ( int row = 0; row < grid.length; row++ ) {
    for ( int col = 0; col < grid.length; col++ ) {
        // this section will usually be in a function
        // checks neighbours of the current "cell"
        try {
            for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
                for ( int colMod = -1; colMod <= 1; colMod++ ) {
                    if ( someVar == grid[row+rowMod][col+colMod] ) {
                        // do something
                    }
                }
            }
        } catch ( ArrayIndexOutOfBoundsException e ) {
            // do nothing, continue
        }
        // end checking neighbours
    }
}

我不禁想到使用異常來使我的代碼工作的原因導致效率低下,所以我正在尋找有關如何在不犧牲可讀性的情況下如何從代碼中消除對異常的依賴的建議,以及我將如何做的建議。此代碼段通常更有效。 提前致謝。

你可以試試看 首先確定網格的大小,假設其為8 X 8並分配MIN_X = 0,MIN_Y = 0,MAX_X = 7,MAX_Y = 7

您當前的職位由thisPosX,thisPosY表示,然后嘗試以下操作:

int startPosX = (thisPosX - 1 < MIN_X) ? thisPosX : thisPosX-1;
int startPosY = (thisPosY - 1 < MIN_Y) ? thisPosY : thisPosY-1;
int endPosX =   (thisPosX + 1 > MAX_X) ? thisPosX : thisPosX+1;
int endPosY =   (thisPosY + 1 > MAX_Y) ? thisPosY : thisPosY+1;


// See how many are alive
for (int rowNum=startPosX; rowNum<=endPosX; rowNum++) {
    for (int colNum=startPosY; colNum<=endPosY; colNum++) {
        // All the neighbors will be grid[rowNum][colNum]
    }
}

您可以分2個循環完成它。

所以rowcol當前包含我要檢查其鄰居的單元格的坐標。 因此,如果我有一個名為START_OF_GRID的類變量,其中包含0 ,則解決方案如下:

int rowStart  = Math.max( row - 1, START_OF_GRID   );
int rowFinish = Math.min( row + 1, grid.length - 1 );
int colStart  = Math.max( col - 1, START_OF_GRID   );
int colFinish = Math.min( col + 1, grid.length - 1 );

for ( int curRow = rowStart; curRow <= rowFinish; curRow++ ) {
    for ( int curCol = colStart; curCol <= colFinish; curCol++ ) {
        // do something
    }
}

為什么不能在訪問數組之前檢查row + rowMod和col + colMod的有效性?

就像是:

 r=row+rowMod;
 c=col+colMod;
 if (r < 0 || c < 0 || r >= grid.length || c >= grid.length) continue;

或者(不繼續 ):

 if (r >= 0 && c >= 0 && r < grid.length && c < grid.length && 
     someVar == grid[r][c]) { /* do something */ }

這個怎么樣:

private static void printNeighbours(int row, int col, int[][] Data, int rowLen, int colLen)
{
    for(int nextR=row-1; nextR<=row+1; nextR++)
    {
        if(nextR<0 || nextR>=rowLen)
            continue;  //row out of bound
        for(int nextC=col-1; nextC<=col+1; nextC++)
        {
            if(nextC<0 || nextC>=colLen)
                continue;  //col out of bound
            if(nextR==row && nextC==col)
                continue;    //current cell
            System.out.println(Data[nextR][nextC]);
        }
    }
}

基本原則是不要訪問超出范圍的內容-因此要么保護范圍,要么首先不要超出范圍。 也就是說,從您不會立即越界的地方開始,然后在越界之前停止。

for ( int row = 1; row < grid.length - 1; row++ ) {
    for ( int col = 1; col < grid.length - 1; col++ ) {
        // this section will usually be in a function
        // checks neighbours of the current "cell"
        for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
            for ( int colMod = -1; colMod <= 1; colMod++ ) {
                if ( someVar == grid[row+rowMod][col+colMod] ) {
                    // do something
                }
            }
        }
        // end checking neighbours
    }
}

就像您當前的代碼一樣,這不一定能正確處理邊緣條件-也就是說,它將3x3網格應用於矩陣中適合矩陣的所有位置,但不會在3x3網格縮小時將其縮小到2x2、2x3或3x2網格在矩陣的邊緣。 但是,這將允許主體中的一種方法檢查3x3網格以觀察矩陣中的每個單元。

如果我正確地理解了您的代碼,並且正確地猜到了您的擔憂,那么您將避免在目標單元格位於網格的一側時避免檢查不存在的鄰居。 一種可能適合您的應用程序或可能不適合您的應用程序的方法是在整個網格周圍放置一個1單元寬的邊框。 然后,您可以在此擴展網格的內部運行循環,並且您檢查的所有單元格都有4個鄰居(如果計算對角相鄰的單元格,則為8個)。

private void fun(char[][] mat, int i, int j){
    int[] ith = { 0, 1, 1, -1, 0, -1 ,-1, 1};
    int[] jth = { 1, 0, 1, 0, -1, -1 ,1,-1};
     // All neighbours of cell
     for (int k = 0; k < 8; k++) {
            if (isValid(i + ith[k], j + jth[k], mat.length)) {
                //do something here 
            }
        }
}

private boolean isValid(int i, int j, int l) {
        if (i < 0 || j < 0 || i >= l || j >= l)
            return false;
        return true;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM