【问题标题】:How to stop Breadth-first search recursive function如何停止广度优先搜索递归函数
【发布时间】:2018-02-18 05:50:43
【问题描述】:

我想在到达指定单元格后停止广度优先搜索功能。

现在我在到达指定单元格后显示一个警报,但仍会访问剩余的节点。你可以看到这种行为here(请选择广度优先搜索)。

function drawBreadthFirstSearch(current, start, last, queue, animation_speed) {
    setTimeout(function () {
        if (queue.length >= 0) {
            current = queue.shift();

            if (current !== last) {
                current.color = "#c6e0b4";
                current.changeColor();
            } else {
                alert('The end!')
                return
            }

            var childs = checkNeigbors(current.i, current.j)
            if (childs) {
                childs.forEach(function (child) {
                    if (child.visited === false) {
                        child.color = "green";
                        child.changeColor();

                        queue.push(child)
                        child.visited = true;
                        drawBreadthFirstSearch(current, start, last, queue, animation_speed)
                    }
                });
            }
        }
    }, animation_speed);
}

函数checkNeigbors 返回单元格数组。

forEach 更改为for 没有帮助。

【问题讨论】:

  • 您缺少一些;。在“结束”行和之后的return 中没有;。同样在queue.push(child) ...
  • 谢谢,但它不能解决我的问题。
  • 这个算法不是广度优先的,而是深度优先的,除此之外(我对 javascript 并不完全精通)看起来它是异步的,这会在正确时中止发现函数很棘手。
  • @Paul,它是广度优先的(不要被你应该首先选择“广度优先”的链接误导)。
  • @NikitaYunoshev,作为旁注,我不认为当前动画与深度优先动画进行公平比较。对于广度优先,您可以同时为处于同一级别的所有节点设置动画,而在深度优先中,您可以一个一个地很好地显示每个访问过的节点。我认为广度优先应该是一样的。这是你想要还是不想要的东西?

标签: javascript algorithm search


【解决方案1】:

它继续的原因是forEach 循环将启动几个递归调用,它们都会启动一个计时器。因此,待定计时器的数量会随着搜索树宽度的增加而增加。并且结束 one 定时器的回调不会阻止其他挂起的定时器执行它们的回调。

一个快速的解决方法是在找到匹配项后立即使队列为空。由于计时器回调仅在队列不为空时执行某些操作,并且队列引用在所有函数调用之间共享,因此您可以避免任何进一步的搜索。

        queue.length = 0; // <--- add this.
        alert('The end!')
        return

【讨论】:

  • 谢谢您,先生。它有帮助。我知道 forEach 启动了几个递归调用,但我已经尝试过“queue = []”但没有帮助)
  • queue = [] 没有帮助,因为这只会更改局部变量,然后该变量将指向内存中的 new 数组,而不会影响 original 的内存位置 数组:它与queue 引用的原始数组分离,其他函数调用仍将查看原始数组。相反,您必须改变所有这些queue 变量所引用的对象,然后他们都会看到变化。
【解决方案2】:

要在到达已搜索的单元格后停止对后代和兄弟姐妹的迭代,您应该在三个地方使用返回值:

首先,当到达所需的单元格时,您应该通知即将发生的递归实例搜索已经结束:

        } else {
            alert('The end!');
            return false;
        }

如果我们找到了请求的单元格,第二个返回命令应该在 forEach 循环中,以便停止迭代节点的子节点:

                      if (!drawBreadthFirstSearch(current, start, last, queue, animation_speed)) return false;

第三个返回命令应该在函数的最后一行,它代表:仍然没有找到单元格,继续搜索:

        }, animation_speed);
        return true;
   }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-02
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多