我目前正在恢复旧的作业分配,在其中编写的程序除其他功能外,还涉及使用Dijkstra算法在图形中找到最短路径。
我想我大部分时候都做对了,但是NullPointerException
执行时我一直保持在第58行if(currentNode.getAktuell())
。
我一直在尝试几种解决方案,但似乎无法弄清楚出什么问题了,但是当队列为空时prioQueue.poll();
返回null
。我试图处理最后currentNode
最终变为null的最后一个问题,但一直无法找到有效的解决方案,因此我开始认为我错过了这里的内容。
如果熟悉dijkstras算法的人可以在这里帮助我,我将非常感激。该算法可能有一个更好的解决方案,但我只需要帮助找出我写的问题出在哪里,而不是使用别人的算法来“解决”。
public static List<String> shortestPath(Graph<String> graph, String från, String till){
//if(!pathExists(graph, från, till))
//return null;
PriorityQueue<DjikstraObjekt<String>> prioQueue = new PriorityQueue<DjikstraObjekt<String>>();
LinkedHashMap<String, DjikstraObjekt<String>> samling = new LinkedHashMap<String, DjikstraObjekt<String>>();
for(String bla : graph.getNodes())
samling.put(bla, new DjikstraObjekt<String>(bla, Integer.MAX_VALUE, null, false));
samling.get(från).updateVikt(0);
prioQueue.add(samling.get(från));
while(!samling.get(till).getAktuell())
{
DjikstraObjekt<String> currentNode = prioQueue.poll();
if(currentNode==null)
break;
if(currentNode.getAktuell())
continue;
currentNode.aktuellNod();
for(ListEdge<String> edge : graph.getEdgesFrom(currentNode.getNode()))
{
System.out.println("get edges from");
int nyVikt = edge.getVikt() + currentNode.getVikt();
DjikstraObjekt<String> toNode = samling.get(edge.getDest());
if(!toNode.getAktuell() && nyVikt < toNode.getVikt()) {
toNode.updateVikt(nyVikt);
toNode.setFrån(currentNode.getNode());
prioQueue.add(toNode);
}
}
}
List<String> djikstaList = new ArrayList<String>();
for(int i=0;i<samling.size();i++){
if(samling.get(i).getNode()!=från){
System.out.println(samling.get(i).getNode());
djikstaList.add(samling.get(i).getNode());
}
}
return djikstaList;
}
public class DjikstraObjekt<E> implements Comparable<DjikstraObjekt<E>> {
private E nod;
private int vikt;
private E frånNod;
private boolean aktuellNod=false;
public DjikstraObjekt(E nod, int vikt, E frånNod, boolean aktuellNod){
this.nod=nod;
this.vikt=vikt;
this.frånNod=frånNod;
this.aktuellNod=aktuellNod;
}
public E getNode() {
return nod;
}
public void updateVikt(int nyvikt){
vikt=nyvikt;
}
public int getVikt() {
return vikt;
}
public boolean getAktuell() {
return aktuellNod;
}
public void aktuellNod(){
aktuellNod=true;
}
public void setFrån(E från)
{
frånNod = från;
}
public int compareTo(DjikstraObjekt<E> other) {
return getVikt() - other.getVikt();
}
}
这是我的listEdge类:
public class ListEdge<E> {
private E dest;
private String namn;
private Integer vikt;
public ListEdge(E dest, String namn, Integer vikt){
this.dest=dest;
this.namn=namn;
this.vikt=vikt;
}
public E getDest(){
return dest;
}
public void ändraVikt(Integer nyVikt){
if(vikt<0)
throw new IllegalArgumentException();
vikt=nyVikt;
}
public String getNamn(){
return namn;
}
public int compareTo(ListEdge other) {
return this.vikt.compareTo(other.getVikt());
}
public int getVikt(){
return vikt;
}
public String toString(){
return "till " + dest + " med " + namn +" "+ vikt;
}
}
这些应该是我的ListGraph类的relevent方法:
public List<E> getNodes(){
List<E> temp = new ArrayList<E>();
for(E test : noder.keySet()){
temp.add(test);
}
return temp;
}
public List<ListEdge<E>> getEdgesFrom(E nod) {
List<ListEdge<E>> temp = new ArrayList<ListEdge<E>>();
if(noder.containsKey(nod)){
try{
for(Map.Entry<E, List<ListEdge<E>>> test : noder.entrySet()){
if(test.getKey().equals(nod)){
System.out.println(nod+" "+test.getKey());
for(ListEdge<E> e: test.getValue()){
temp.add(e);
}
}
}
}
catch(NoSuchElementException E){
}
}
return temp;
}
我无法重建您告诉我们的NullPointerException。正如Leandro指出的那样,问题可能出在ListEdge和Graph的实现上。
我自己做了两个类的实现,以测试您的代码。
我唯一能找到的问题是最后创建结果列表:
for(int i=0;i<samling.size();i++){
if(samling.get(i).getNode()!=från){
这将始终导致,NullPointerException
因为get()
需要键,而在您的情况下为String
,而不是int
。要遍历地图,请使用类似
List<String> djikstaList = new ArrayList<String>();
for(String key : samling.keySet()){
if(samling.get(key).getNode()!=från){
System.out.println(samling.get(key).getNode());
djikstaList.add(samling.get(key).getNode());
}
}
此外,我想你wan't从返回的实际路径from
来to
,所以你需要一个getter添加getFrån()
到DijkstraObjekt
,然后建立列表如下:
String fromNode = samling.get(to).getNode();
djikstaList.add(to);
while(fromNode != from){
fromNode = samling.get(fromNode).getFrån();
djikstaList.add(fromNode);
}
此后,列表将以相反的顺序包含完整的路径(包括“开始”和“结束”节点)。
如果需要,我可以发布所有用于测试/调试的类。
干杯
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句