使用 Dijkstra 算法的最短路径
我目前正在复习一项旧的家庭作业,其中我正在编写一个程序,其中包括使用 Dijkstra 算法查找图中的最短路径。
我认为我的大部分内容都是正确的,但在执行 if(currentNode.getAktuell())
时,我在第 58 行不断收到 NullPointerException
。
我一直在来回尝试几种解决方案,但似乎无法找出问题所在,但当队列为空时, prioQueue.poll();
返回 null
。我试图处理最后一个最终变成 null 的 currentNode
但一直无法找到有效的解决方案,所以我开始认为我在这里错过了一些东西。
如果熟悉 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 类中的相关方法:
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;
}
I'm currently reviving an old homework assignment, where I'm writing a program that among other functions, involves finding the shortest path in a graph using Dijkstra's algorithm.
I think I've got it right for the most part, but I keep getting NullPointerException
at line 58 when executing if(currentNode.getAktuell())
.
I've been trying several solutions back and forth but can't seem to figure out what is wrong but prioQueue.poll();
returns null
when the queue is empty. I've tried to handle that last currentNode
that eventually turns into null but have not been able to find a working solution, so I'm starting to think that I've missed out on something here.
I would really appreciate it if someone familiar with dijkstras algorithm could help me out here. There's probably a better solution to the algorithm but I only want help with finding out what is wrong with the one I've written, and not "the answer" using someone else's algorithm.
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();
}
}
Heres my listEdge class:
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;
}
}
These should be the relevent methods from my ListGraph class:
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我无法重建您告诉我们的 NullPointerException。正如 Leandro 指出的,问题可能出在 ListEdge 和 Graph 的实现上。
我自己实现了这两个类来测试您的代码。
我能发现的唯一问题是最后创建结果列表的位置:
这将始终导致
NullPointerException
因为get()
需要一个键,在您的情况下是一个String
,而不是一个int
。要迭代地图,请使用类似的东西此外,我假设您不想返回从
from
到to
的实际路径,因此您需要添加一个 gettergetFrån()
到DijkstraObjekt
,然后像这样构建列表:此后,列表将以相反的顺序包含完整路径(包括开始和结束节点)。
如果需要,我可以发布我用于测试/调试的所有课程。
干杯
坦纳利
I couldn't reconstruct the NullPointerException you told us about. As Leandro pointed out, the problem might lay with your implementation of ListEdge and Graph.
I did an implementation of both classes myself to test your code.
The only problem I could find was in the end where you create the result list:
This will always Result in a
NullPointerException
becauseget()
expects a key and in your case that's aString
, not anint
. To iterate over the Map use something likeFurthermore, i assume you wan't to return the actual path from
from
toto
so you would need to add a gettergetFrån()
toDijkstraObjekt
and then build up the list like this:After this the List will contain the complete path (including Start and End node) in reverse order.
If wanted, I can post all of my classes I used for testing/debugging.
Cheers
tannerli
我认为这可能是一个问题:
编辑:
抱歉,我以为 {} 在那里。那里一切都很好。我会继续寻找。
I think this might be a problem:
EDIT:
Sorry I thought the {} is there. Everything is ok there. I will keep looking.
也许试试这个:
Maybe try this: