我正在尝试为多个节点实现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;
}
谢谢你,对不起代码的大墙。
答案 0 :(得分:1)
在你的重置功能中:
public void reset() {
this.minDistance = Double.POSITIVE_INFINITY;
}
我建议你也重置之前的
public void reset() {
this.minDistance = Double.POSITIVE_INFINITY;
this.previous = null;
}
或者在向后追踪路径时会得到一个无限循环。