寻找周围相邻网格节点个数

来源:互联网 发布:windows 2008 r2 iis 编辑:程序博客网 时间:2024/04/30 08:19

2011/05/10

 

在看Game Of Life的源码的时候,发现lifeSan()方法有段处理,摘出分析。

 

寻找周围相邻网格节点个数,假设在7*7的网格上如下1表示存在节点:

 

life[0] 0 0 0 0 0 0 0
life[1] 0 0 0 0 0 0 0
life[2] 0 0 0 0 0 0 0
life[3] 0 0 1 1 1 0 0
life[4] 0 0 1 0 0 0 0
life[5] 0 0 0 0 0 0 0
life[6] 0 0 0 0 0 0 0

 

要找出(3,2)节点周围存在几个节点,或者所有节点节点周围存在节点都找出来。

 

算法1

    for(int i = 0; i < life.length; i++){

        for(int i = 0; i < life.length; i++){

            if(life[i][j] == 1){

                //在边界范围内,遍历八个方向:左上,上,右上,左,右,左下,下,右下。存在1则计数器加1。

            }

        }

    }

这种算法很适合我们的的思维,使用时间n*m * 8,空间不变。

 

算法2

开辟一个n+2,m+2的数组,刚好大一圈。初始化数组为各项为0。用时(n+2)*(m+2)

ai[0] 0 0 0 0 0 0 0 0 0
ai[1] 0 0 0 0 0 0 0 0 0
ai[2] 0 0 0 0 0 0 0 0 0
ai[3] 0 0 1 2 3 2 1 0 0
ai[4] 0 0 2 2 3 1 1 0 0
ai[5] 0 0 2 2 4 2 1 0 0
ai[6] 0 0 1 1 1 0 0 0 0
ai[7] 0 0 0 0 0 0 0 0 0
ai[8] 0 0 0 0 0 0 0 0 0

 

/*
 * 如果life数组中life[i][j] = 1则,设置al数组[i][j]四周都是+1
 * 1 1 1
 * 1 0 1
 * 1 1 1
 * 叠加之后,就可以算出life[i][j]点周围有几个节点,就是al[i][j]的值。
 */

for (int k1 = 1; k1 < rows + 1; k1++) {
    for (int k = 1; k < cols + 1; k++)
        if ((life[k1 - 1][k - 1] & 1) == 1) {
            ai[k1 - 1][k - 1]++;
            ai[k1 - 1][k]++;
            ai[k1 - 1][k + 1]++;
            ai[k1][k - 1]++;
            ai[k1][k + 1]++;
            ai[k1 + 1][k - 1]++;
            ai[k1 + 1][k]++;
            ai[k1 + 1][k + 1]++;
        }
}

原理是相当于事件触发一样,如果life有节点,我就通知周围一次事件,因为是彼此相邻的。所以事件最终累计值就是该节点周围的节点数。

这种算法,时间是n*m * 8+(n+2)*(m+2),空间加倍。其实空间没有变化,因为第一种计数器需要数组变量count[n][m]存储,如果说空间的确是变多出row和col都加2这一小块空间。

 

第二种算法不如第一种,时间都消耗的是成倍,但是我们再分析下,时间成倍其实是用在数组的初始化上。而第一种count[n][m]数组同样也要初始化,所以时间也没有变化。那如果说初始化时间有多出+2这一点时间,那时肯定的。

但是如果不创建出一个大一圈的话,count[][]数组在计数的时候,要对遍历八个方向的判断数组是否越界了。这点处理时在每次循环的时候做的。加上去的话,第一种的算法时间也和第二种一样了。

 

总之,两种都可以使用,但是如果有扩展,比如多次从某个坐标取周围节点,只要直接取就可以了。

采用第二种比较方便。