递归数组遍历问题

时间:2009-06-10 21:17:38

标签: java

我遇到了一些stackoverflow问题,希望有人可以让我对非递归解决方案有所了解。

Ident[][] map = ...

private int explore(Ident item, int xcoord, int ycoord) {
    if ((map[xcoord][ycoord] == null) || !map[xcoord][ycoord].equals(item))
             return 0;

    map[xcoord][ycoord] = null;
    int sumX, sumY, counter = 1;
    item.translate(xcoord, ycoord);

    for (int y = -1; y <= 1; y++)
        for (int x = -1; x <= 1; x++) {
             sumX = x + xcoord;
             sumY = y + ycoord;
            if (((y != 0) || (x != 0)) && (sumX >= 0) && (sumX < map.length) && 
                     (sumY >= 0) && (sumY < map.[0].length))
                     counter += explore(item, sumX, sumY);
             }
        }
    }
    return counter;
}

该方法给出了一个Ident对象的二维数组,一个目标Ident和一个数组内的起始位置。它以递归方式遍历数组 计算Ident占据的连续区域的大小。它还将输入的Ident项目集中在该区域的中间。

通过遍历map数组并在任何非null元素上调用explore方法,我可以构建一个以其区域为中心的Ident项数组,并且相对于它们的区域具有大小。

可以看到除了小地图以外的任何东西,堆栈都会溢出。

任何人都有另一种方法来完成同样的任务吗?还是有些见解可以帮我找到一个?

2 个答案:

答案 0 :(得分:2)

要消除递归,请在其包含任何项目时创建要探索和循环的坐标列表;在你的循环中,构建一个新的坐标列表进行探索,在循环结束时,用新列表替换旧列表。

答案 1 :(得分:1)

这让我回到80年代中期。任何泛洪填充算法都需要一定量的状态。遗憾的是我不记得算法了。大范围的效率可能不会对迷宫有效。

为了避免递归而不是递归,只需将您调用的数据添加到堆栈中。循环从堆栈顶部弹出下一个未探测的坐标。使用堆栈而不是FIFO队列可以稍微改善一下位置,虽然它可能不会在这里产生巨大的差异。

private int explore(Ident item, int xcoord, int ycoord) {
    int counter = 0;

    Queue<Point> stack = Collections.asLifoQueue(new ArrayDeque<Point>());
    stack.add(new Point(xcoord, ycoord));

    while (!stack.isEmpty()) {
        Point point = stack.remove();
        xcoord = point.x;
        ycoord = point.y;

        if (!item.equals(map[xcoord][ycoord])) {
            continue;
        }

        ++counter;
        map[xcoord][ycoord] = null;
        item.translate(xcoord, ycoord);

        for (int y = -1; y <= 1; y++)
            for (int x = -1; x <= 1; x++) {
                 int sumX = x + xcoord;
                 int sumY = y + ycoord;
                 if (
                     !(x == 0 && y == 0) &&
                     0 <= sumX && sumX < map.length &&
                     0 <= sumY && sumY < map[0].length
                 ) {
                     stack.add(new Point(sumX, sumY));
                 }
            }
        }
    }
    return counter;
}

在stackoverflow的最佳传统中,这还没有看到编译器。 (它也保留了原始算法的大部分内容。)