在二维阵列中协调接近度

时间:2014-07-10 14:30:30

标签: java multidimensional-array

我有一个类型为Animal的二维数组(用户定义的类型)。我已设置数组,以便随机填充PreyPred类型Animal或任何内容(保留null)。

我的问题是关于接近度,我想知道Prey是否在Pred(包括对角线)旁边的空格中。说我有这个:

{null, null, null,    
 null, Prey, null,
 Pred, null, null}

假设我使用:

Animal[][] grid = new Animal[3][3];

如果我只是说:

for (int i = 0; i < 3; i++){
    for(int j = 0; j <  3; j++){
        if (grid[i+1][j] == Pred || grid[i+1][j+1] == Pred || grid[i+1][j+1] == Pred
        || grid[i][j+1] == Pred || grid[i-1][j+1] == Pred || grid[i+1][j] == Pred
        || grid[i-1][j] == Pred || grid[i-1][j-1]) == Pred) // Then proximity = true.
    }
}

这会非常低效吗?整个数组是否必须通过8次搜索来检查if语句是否返回true?

我需要将数组扩展到几千个&#34;空间&#34;我想要一种不会花费太多时间的方法。

如果这种方式效率低下,任何人都可以建议更好(也许更清洁)的方法吗?

4 个答案:

答案 0 :(得分:1)

如果要检查2D数组中的每个可能索引,您似乎必须执行n^2算法。

您希望确保每个true语句的优先级为if这四个条件:

  1. i+1 < grid.length
  2. i-1 >= 0
  3. j+1 < grid[i].length
  4. j-1 >= 0
  5. 遵循此伪代码以避免错误:

    boolean proximity = false;
    for (int i = 0; i < grid.length; i++){
        for(int j = 0; j <  grid[i].length; j++){
            if(grid[i][j] == Pred){  //only care if its a Pred
                //now check for Prey
                //make sure youre not out of bounds!
                if(i+1 < grid.length && grid[i+1][j] == Prey) proximity = true;
                else if(i+1 < grid.length && j+1 < grid[i].length && grid[i+1][j+1] == Prey) proximity = true;
                //do for rest etc.
            }
            if(proximity) break;//once found, youre done.
        }
    }
    

答案 1 :(得分:0)

如果许多职位为空,哟可以使用这种方法。您可以从左到右和从上到下遍历矩阵。当你找到Pred时,只检查8个比较。另外,当您检查前一个单元格(西)和上面一行(西北,北,东北)上的单元格时,您已查看当前单元格,您不需要检查8个位置,只有这个四:如果包含Pred

,则当前单元格的东,东南,南和西南单元格
for (int i = 0; i < 3; i++){
    for(int j = 0; i <  3; j++){
       if(grid[i][j] == Pred)
       {
          if (grid[i][j+1] == Prey || grid[i+1][j-1] == Prey || grid[i+1][j] == Prey
            || grid[i+1][j+1] == Prey ) // Then proximity = true.
       }
       if(grid[i][j] == Prey)
       {
          if (grid[i][j+1] == Pred || grid[i+1][j-1] == Pred || grid[i+1][j] == Pred
            || grid[i+1][j+1] == Pred ) // Then proximity = true.
       }
    }
}

注意双边接近度,如果grid [i] [j]与网格[i + 1] [j + 1]接近,则网格[i + 1] [j + 1]接近格[i] [j]。

此外,您必须牢记矩阵的界限。如果您在最后一栏,请不要检查下面的行,如果您在第一列,请不要检查左侧的列,如果您是,请不要检查右侧的列在最后一栏。 (有了这个方法,你永远不会检查上面的行,所以不要担心上限)

编辑并更正。你还必须注意到bilareal的接近程度。

答案 2 :(得分:0)

你可以创建如下函数:

public boolean containsPreditor(int x, int y, Animal[] grid)
{
    boolean outOfBounds = false;
    if(x < 0 || x >= grid[0].length)
    {
         outOfBounds = true;
    }
    if(y < 0 || y >= grid.length)
    {
         outOfBounds = true;
    }

     if(!outOfBounds)
     {
      return grid[y][x] == Pred;
     }
     else
     {
      //space does not exist
      return false;
     }

}

然后你可以运行3x3网格的方法,或者通过修改循环大小你想要它的大小

    boolean proximity = false;
    int xIndex; //assign this
    int yIndex; //assign this too
 for(int i = (yIndex - 1); i <= (yIndex + 1); i++)
 {
      for(int j = (xIndex - 1); j <= (xIndex + 1); j++)
       {
          proximity = proximity || containsPreditor(j, i, Animals);
       }
 }

基本上是相同的,但更容易理解和调试

答案 3 :(得分:0)

我为你做了一夜之间的思考,并意识到通过将电路板表示为一个集合,然后使用位逻辑来组合,可以更快地完成。这种方法特别适用于CPU和CPU缓存,但它确实需要一些前期计算,理想情况下是存储板的方式的变化。如果你不能这样做,那么将需要克服一些开销。但是值得付出努力!

基本算法是:

preyAtRisk = bitCount( squaresAtRisk.bitAnd(squaresWithPrey) )

该算法可以用非常少的条件跳转来实现,现代CPU可以在单个cpu周期中执行64位,并且大多数JVM为Integer.bitCount和Long.bitCount提供内在函数,用一个汇编指令替换它们。因此,许多循环可以在硬件中并行完成。那就是,快!

此算法要求将电路板表示为位集。因此对于3x3电路板,第一个方块将是第一个位,依此类推,直到第九个方块为第九位。

因此你的例子是

{null, null, null,    
 null, Prey, null,
 Pred, null, null}

将由以下两个位集

表示
prey  = 000 010 000
preds = 000 000 100

然后我们需要将preds位集转换为代表哪些方块有风险的位集。这可以通过预先计算每个正方形的方块将处于危险中的位组来完成。看起来像这样:

dangerZones[0] = 010 110 000
dangerZones[1] = 101 111 000
dangerZones[2] = 010 011 000
...

然后当preds被添加到集合中,或者在它自己的迭代中,可以构建squareAtRisk:

public void setPred( x, y ) {
  bitIndex       = toBitIndex(x,y)
  squaresAtRisk &= dangerZones[bitIndex]
}