【问题标题】:A-Star Algorithm: Slow ImplementationA-Star 算法:实施缓慢
【发布时间】:2015-01-11 15:34:46
【问题描述】:

我正在用 javascript 实现 A-Star 算法。它可以工作,但是在两个非常靠近的点之间创建路径需要很长时间:(1,1)到(6,6)需要几秒钟。我想知道我在算法中犯了哪些错误以及如何解决这些错误。

我的代码:

Node.prototype.genNeighbours = function() {
    var right = new Node(this.x + 1, this.y);
    var left = new Node(this.x - 1, this.y);
    var top = new Node(this.x, this.y + 1);
    var bottom = new Node(this.x, this.y - 1);
    this.neighbours = [right, left, top, bottom];
}

AStar.prototype.getSmallestNode = function(openarr) {
    var comp = 0;
    for(var i = 0; i < openarr.length; i++) {
        if(openarr[i].f < openarr[comp].f) comp = i
    }
    return comp;
}

AStar.prototype.calculateRoute = function(start, dest, arr){
var open = new Array();
var closed = new Array();

start.g = 0;
start.h = this.manhattanDistance(start.x, dest.x, start.y, dest.y);
start.f = start.h;
start.genNeighbours();
open.push(start);
while(open.length > 0) {
    var currentNode = null;
    this.getSmallestNode(open);
    currentNode = open[0];
    if(this.equals(currentNode,dest)) return currentNode;
    currentNode.genNeighbours();
    var iOfCurr = open.indexOf(currentNode);
    open.splice(iOfCurr, 1);
    closed.push(currentNode);
    for(var i = 0; i < currentNode.neighbours.length; i++) {
        var neighbour = currentNode.neighbours[i];
        if(neighbour == null) continue;
        var newG = currentNode.g + 1;
        if(newG < neighbour.g) {
            var iOfNeigh = open.indexOf(neighbour);
            var iiOfNeigh = closed.indexOf(neighbour);
            open.splice(iOfNeigh, 1);
            closed.splice(iiOfNeigh,1);
        }
        if(open.indexOf(neighbour) == -1 && closed.indexOf(neighbour) == -1) {
            neighbour.g = newG;
            neighbour.h = this.manhattanDistance(neighbour.x, dest.x, neighbour.y, dest.y);
            neighbour.f = neighbour.g + neighbour.h;
            neighbour.parent = currentNode;
            open.push(neighbour);
        }
    }

}
}

编辑:我现在已经解决了这个问题。这是因为我只是在调用: open.sort();它没有按节点的“f”值对节点进行排序。我写了一个自定义函数,现在算法运行得很快。

【问题讨论】:

  • 什么是genNeighbors()?您的优先队列在哪里?
  • 谢谢@Bergi。你让我意识到了问题所在。我没有对节点进行适当的排序。
  • 这不是唯一的错误,我会写一个答案。
  • 好的,谢谢。这是我第一次实现该算法,所以欢迎任何指针:)
  • 欢迎您回答自己的问题,但您必须使用“回答您的问题”按钮才能将其作为答案归档并获得投票和接受。

标签: javascript a-star


【解决方案1】:

我发现的一些错误:

  • 您的open 节点集没有任何结构,因此很容易检索距离最小的节点。通常的选择是使用优先级队列,但按排序顺序插入新节点(而不是open.push(neighbour))就足够了(起初)。
  • 在您的 getSmallestNode 函数中,您可以在索引 1 处开始循环
  • 您正在调用getSmallestNode(),但根本没有使用它的结果。你每次只取currentNode = open[0];(然后甚至搜索它的位置来拼接它!它是0!)。有了队列,就只有currentNode = open.shift()

然而,最重要的(可能是最错误的)是你的getNeighbors() 函数。它确实会在每次调用时创建全新节点对象——这些对象以前闻所未闻,并且您的算法(或其closed 集)不知道这些对象。它们可能与其他节点在您的网格中的位置相同,但它们是不同的对象(通过引用进行比较,而不是通过相似性进行比较)。这意味着indexOf永远closed 数组中找到那些新邻居,它们将被一遍又一遍地处理(一遍又一遍)。我不会尝试计算这个实现的复杂性,但我猜它甚至比指数还要糟糕。

通常,A* 算法在已经存在的图上执行。 OOP-getNeighbors-函数将返回对现有节点对象的引用,而不是创建具有相同坐标的新对象。如果您需要动态生成图形,则需要一个查找结构(二维数组?)来存储和检索已经生成的节点。

【讨论】:

  • 感谢您的详细解答。将努力实施您的一些建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-27
  • 1970-01-01
  • 2012-02-06
  • 1970-01-01
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多