代码说明: 所以我正在为ASCII地图实现A *最短路径算法,可传递的字段在数组中(map [] [])。 我有一个PriorityQueue,以及两个用于Dijkstra-distance(d)和启发式(h)的HashMaps,它们分别用伪无限和欧几里德距离初始化。
相关的while循环获取优先级队列的元素u,然后检查其邻居v是否可以更好地了解它们的距离。
我的问题: 在标记的行中,在d中找不到v(对于v =(171,434)),因此我得到一个空指针异常,尽管对于队列的每个元素,在d和h中都有一个初始值。正如您在注释行中看到的那样,我检查它是否(171,434)被添加到优先级队列中,但它没有,但它以某种方式传递了上面的if子句。知道它怎么会潜入?
Map<Point, Double> aStar(Point start, Point end){
Map<Point, Double> d = new HashMap<Point, Double>();
Map<Point, Double> h = new HashMap<Point, Double>();
PriorityQueue<Point> queue = new PriorityQueue<Point>(fieldCount,new AStarComparator(d,h));
for(int i=0;i<map.length;i++){
for(int j=0;j<map[i].length;j++) {
Point p = new Point(i,j);
if(!p.equals(start) && map[i][j]) {
d.put(p, Double.MAX_VALUE);
h.put(p, p.distance(end));
queue.add(p);
//if(p.equals(new Point(171,434)))
// System.out.println("Added " + p + " with d = " + d.get(p));
}
}
}
d.put(start, 0.0);
h.put(start, start.distance(end));
queue.add(start);
//System.out.println("Added " + start + " with d = " + d.get(start));
while(!queue.isEmpty()){
System.out.println("Polling " + queue.peek());
Point u = queue.poll();
Point v = new Point();
for(int i= -1; i <= +1; i++) {
for(int j= -1; j <= +1; j++) {
v.x = u.x + i;
v.y = u.y + j;
if(queue.contains(v)){
--> System.out.println("u = " + u + ", v = " + v + ", d.get(v) = " + d.get(v) + ", d.contains(v) = " + d.containsKey(v));**
double weight = (i == 0 || j == 0) ? 1 : Math.sqrt(2);
--> if(d.get(u) + weight < d.get(v)) {
d.put(v, d.get(u) + weight);
//refresh queue
queue.remove(v);
queue.add(v);
System.out.println("Refreshing with " + v);
}
}
}
}
}
return d;
}
修改
Stacktrace(117是if子句的行):
java.lang.NullPointerException
at StarcraftShortestPath.aStar(StarcraftShortestPath.java:117)
at StarcraftShortestPath.findPath(StarcraftShortestPath.java:141)
at StarcraftTest.test1stRoute(StarcraftTest.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
答案 0 :(得分:1)
删除然后添加相同的东西完成任何事情。这是一个错误。您应该在更新之前删除v
,然后再添加它。
还有第二个错误:每次围绕内循环必须使用新的v
。如果您使用相同的v
,则在不告知PQ的情况下更新它,如果PQ按照这些值排序,则会破坏PQ。