避免调用堆栈错误

Avoiding call stack error

我知道 call stack size exceeded 是什么意思,但我需要一种解决方法。

当我调用这个递归函数时我明白了

function fill(x_y) {
    var locColor = getPx(x_y[0], x_y[1]);
    if (locColor != pref.color) {
        setPx(x_y[0], x_y[1], pref.color);
        if (getPx(x_y[0] - 1, x_y[1]) == locColor) {
            fill([x_y[0] - 1, x_y[1]]);
        }
        if (getPx(x_y[0], x_y[1] - 1) == locColor) {
            fill([x_y[0], x_y[1] - 1]);
        }
        if (getPx(x_y[0] + 1, x_y[1]) == locColor) {
            fill([x_y[0] + 1, x_y[1]]);
        }
        if (getPx(x_y[0], x_y[1] + 1) == locColor) {
            fill([x_y[0], x_y[1] + 1]);
        }
    }
}

它用于 canvas 应用程序。

x_y 只是调用填充的 x ​​和 y 坐标。

setPx 在给定的 canvas 坐标上打印一个矩形。

getPx 获取给定坐标 canvas 的矩形的颜色

pref.color 是用户为 setPx

选择的颜色

这个函数可以不用递归完成吗?

此项填写顺序:

  • 离开,
  • 顶,
  • 对了,
  • 底部

(除非我弄错了坐标系)。

可以用x_y的列表来处理,不用递归就可以解决;而不是使用堆栈进行递归,而是使用列表来存储下一次调用的参数。

function fill(x_y) {
    var todo = [x_y];
    var iniColor = getPx(x_y[0], x_y[1]);
    while (todo.length) {
        var curr = todo[0];
        var locColor = getPx(curr[0], curr[1]);
        todo = todo.slice(1);
        if (locColor != iniColor) { continue; }
        if (locColor == pref.color) { continue; }
        setPx(curr[0], curr[1], pref.color);

        todo.push([curr[0]-1,curr[1]  ]);
        todo.push([curr[0],  curr[1]-1]);
        todo.push([curr[0]+1,curr[1]  ]);
        todo.push([curr[0],  curr[1]+1]);
    }
}

更新:2015-03-01

从评论来看,由于迭代次数,这不如问题中的算法。在这个块中,我没有提前检查条件,这意味着它们被添加到 todo 列表中,即使它们可能不是好的候选者。并且在后面处理点的时候,检查条件。

        todo.push([curr[0]-1,curr[1]  ]);
        todo.push([curr[0],  curr[1]-1]);
        todo.push([curr[0]+1,curr[1]  ]);
        todo.push([curr[0],  curr[1]+1]);

解决方法:和问题一样早点检查;在调用 push.

之前