计算多条路径时,Dijkstra算法失败

时间:2015-05-26 18:33:38

标签: java algorithm dijkstra

我正在尝试为多个节点实现Dijkstra算法。例如,我有x个要访问的节点数量,我需要建立一个访问每个节点而不改变它们的顺序的路径,如果路径比那个短,则无关紧要。一切似乎都起作用,但是在超过2个节点后,它在计算路径时失败并且内存不足。我假设我在这里做了一些可怕的事情。

对于这个不明确的问题我很抱歉,但我不确定如何缩短它。

编辑:问题是当'verticesToVisit'列表中添加了3个或更多顶点时,Java在'getShortestPath方法的Java堆空间异常中抛出内存不足,确切的行标记为下面的注释。

无论如何这是我的课程:

Vertice

private List<Edge> adjencies;
private double minDistance = Double.POSITIVE_INFINITY;
private Vertice previous;

public Domicile() {
    adjencies = new ArrayList<Edge>();
    previous = null;
}
public void reset() {
    this.minDistance = Double.POSITIVE_INFINITY;
}
// sets and gets..

边缘

private Vertice target;
private Vertice source; // Not used in algorithm, just for debugging
private double weight;

public Edge(Vertice argSource, Vertice argTarget, double argWeight) {
    source = argSource;
    target = argTarget;
    weight = argWeight;
}
public Edge(){}
// sets and gets

算法:

public void computePaths(Vertice source) {
    source.setMinDistance(0.);
    PriorityQueue<Vertice> vertexQueue = new PriorityQueue<Vertice>();
    vertexQueue.add(source);
    while(!vertexQueue.isEmpty()) {
        Vertice u = vertexQueue.poll();

        for(Edge e : u.getAdjencies()) {
            Vertice v = e.getTarget();
            double weight = e.getWeight();
            double distanceThroughU = u.getMinDistance() + weight;
            if(distanceThroughU < v.getMinDistance()) {
                vertexQueue.remove(v);
                v.setMinDistance(distanceThroughU);
                v.setPrevious(u);
                vertexQueue.add(v);
            }
        }
    }
}
///////////////////////
// This method fails //
///////////////////////
public List<Vertice> getShortestPathTo(Vertice target) {
    List<Vertice> path = new ArrayList<Vertice>();
    for(Vertice vertex = target; vertex != null; vertex = vertex.getPrevious()) {
        path.add(vertex);   // Java runs out of memory "Java heap size" here
    }
    Collections.reverse(path);
    return path;
}

public void resetAllVertices() {
    for(Vertice dom : graph) {
        dom.reset();
    }
}


public List<String> getRoute() {
    List<Vertice> verticesToVisit = dbd.getAllVertice(); // Gets them from database. This part is working.
    Collections.sort(verticesToVisit);
    List<String> result = new ArrayList<String>();
    if(verticesToVisit.isEmpty()) {
        return null;
    }
    else if(patients.size() < 2) {
        result.add(verticestoVisit.get(0).getName());
    } else {

        for(int i = 0; i < verticesToVisit.size()-1; i++) {
            Vertices graphDomStart = findFromGraph(verticesToVisit.get(i).getLocationId()); // finds vertice in graph (in db they dont have edges)
            Vertice graphDomGoal = findFromGraph(verticesToVisit.get(i+1).getLocationId()); // finds vertice in graph (in db they dont have edges)

            computePaths(graphDomStart); // exception is tracked from here
            result.add(formatAddress(getShortestPathTo(graphDomGoal)));

            resetAllVertices();
        }
    }
    return result;
}

private Domicile findFromGraph(int locationId) {
    for(Domicile dom : graph) {
        if(dom.getLocationId() == locationId) {
            return dom;
        }
    }
    return null;
}

谢谢你,对不起代码的大墙。

1 个答案:

答案 0 :(得分:1)

在你的重置功能中:

public void reset() {
    this.minDistance = Double.POSITIVE_INFINITY;
}

我建议你也重置之前的

public void reset() {
    this.minDistance = Double.POSITIVE_INFINITY;
    this.previous = null;
}

或者在向后追踪路径时会得到一个无限循环。