(java) dijkstra algorithmus

felixbray

Newbie
Registriert
Juni 2012
Beiträge
4
Hallo liebe Forummitglieder

ich habe folgendes problem bei dem ihr mir hoffentlich helfen könnt (ihr seit meine letzte Rettung).

Der angehängte dijkstra algorithmus sollte eigentlich funtionieren, allerdings kommt immer ein nullpointer und die randliste ist nicht nach gewicht sortiert was für den algorithmus elementar ist ...

Bitte helft mir.

MFG
felixbray
 

Anhänge

Zuletzt bearbeitet:
Willkommen,

sorry, aber hier ist nix zu sehen. Wo ist das Anhängsel?
 
Code:
public class Dijkstra
{
  private List knoten = new List();
  private List rand = new List();
  private Graph mygraph;
  //länge??

  public Dijkstra(Graph pgraph)
  {
    mygraph = pgraph;
  }

  public List starter(GraphNode pstart, GraphNode ziel)
  {
    DijkstraNode start = new DijkstraNode(pstart, 0.0, pstart);
    if(pstart != ziel)
    {
      mygraph.resetMarks();
      kuerzesterWeg(start, ziel);
    }
    //knoten auslesen
    return wegauslesen(pstart, ziel);
  }

  private void kuerzesterWeg(DijkstraNode startKn, GraphNode zielKn)
  {
    while(!mygraph.allNodesMarked())
    {
      startKn.getvorgängerKn().mark();                                            // markiere Vorgängerknoten
      knoten.append(startKn);
      List nachbar = mygraph.getNeighbours(startKn.getknoten());                  // Nachbarliste des Knotens
      nachbar.toFirst();
      while(nachbar.hasAccess())
      {
        if(!((GraphNode) nachbar.getObject()).isMarked())                         // Nachbar unmarkiert?
        {
          double weight = startKn.getgewicht() + gewicht(startKn.getknoten(),(GraphNode) nachbar.getObject());   // Gesamtgewicht
          DijkstraNode DN = new DijkstraNode(((GraphNode) nachbar.getObject()), weight, startKn.getknoten()) ;     // neuer Dijkstranode
          rand = sort_insert(rand,DN);                                            // nach Gewicht sortiert eingefügt in den Rand
          System.out.println("sortiert eingefügt: " + DN.getknoten().getName() + " mit dem Gewicht: " + weight);
          ((GraphNode) nachbar.getObject()).mark();
        }
        nachbar.next();
      }
      rand.toFirst();
      if(rand.hasAccess())
      {
        DijkstraNode helfer = new DijkstraNode((DijkstraNode) rand.getObject());      // DijkstraNode mit dem kleinsten Gewicht aus dem Rand holen
        rand.remove();                                                                // und aus dem Rand löschen
        System.out.println("rekursiver Aufruf: " + helfer.getknoten().getName());
        kuerzesterWeg(helfer, zielKn);                                                // rekursiver Aufruf
      }
    }
  }

  private List wegauslesen(GraphNode start, GraphNode ziel)
  {
    List weg = new List();
    DijkstraNode dntemp = new DijkstraNode(ziel, 0.0, start);
    GraphNode gntemp = new GraphNode("");
    knoten.toLast();
    while(knoten.hasAccess() || ziel == start)
    {
      dntemp = (DijkstraNode) knoten.getObject();
      gntemp = (GraphNode)dntemp.getknoten();
      if(gntemp.getName().equals(ziel.getName()))
      {
        weg.toFirst();
        weg.insert(gntemp);
        ziel = dntemp.getvorgängerKn();
      }
      knoten.remove();
      knoten.toLast();
    }
    return weg;
  }
  
  
  private double gewicht(GraphNode startKn, GraphNode zielKn)
  {
    if(startKn!=zielKn)
    {
      double gewicht = mygraph.getEdgeWeight(startKn,zielKn);
      return gewicht;
    }
    return 0;
  }
  
  
  private List sort_insert(List prand, DijkstraNode pDN)
  {
    prand.toFirst();            //  springe an den Anfang der Liste
    boolean eingefuegt = false;
    
    if(prand.isEmpty())        // Falls die Liste leer ist
    {
      prand.append(pDN);      System.out.println("1.objekt im rand");
      eingefuegt = true;
    }
    else                      // falls die Liste nicht leer ist
    {
      while (!eingefuegt && prand.hasAccess())
      {
        DijkstraNode aktuelleDN = (DijkstraNode) prand.getObject();
        if(pDN.getknoten() == aktuelleDN.getknoten())
        {
          System.out.println("2 knoten gleich");
          if(pDN.getgewicht() > aktuelleDN.getgewicht())
          {
            eingefuegt = true;     // wenn der schon vorhandene DN ein kleineres Gewicht hat, brauch man nix mehr tun
            System.out.println("vorhandener Knoten hat kleineres Gewicht");
          }
          else
          {
            prand.remove();       // andernfalls: vorhandenen DN löschen und später pDN sortiert einfügen
            System.out.println("vorhandener Knoten gelöscht");
          }
        }
        prand.next();
      }
      
      prand.toFirst();
      
      while (!eingefuegt && prand.hasAccess())  //solange nicht eingefügt und nicht am Ende der Liste
      {
        DijkstraNode aktuelleDN = (DijkstraNode) prand.getObject();
        if (pDN.getgewicht() < aktuelleDN.getgewicht())
              //Falls das übergebene Gewicht kleiner als das Aktuelle (in der Liste) ist
        {
          prand.insert(pDN);   //füge die neue DijkstraNode vor der aktuellen ein
          eingefuegt = true;  // schon eingefügt
          System.out.println("neuer DN eingefügt");
        }
        else  //falls das übergebene Gewicht größer als das aktuelle ist
        prand.next();   //gehe eine Position weiter in der Liste
      }
    }
    System.out.println("jetzt sollte er was zurückgeben");
    return prand;
  }
  
  
}
Code:
public class DijkstraNode
{

  private GraphNode knoten = new GraphNode("");
  private GraphNode vorgängerKn = new GraphNode("");
  private double gewicht=0;
   
  public DijkstraNode(GraphNode pknoten, Double pgewicht, GraphNode pvorgängerKn)
  {
    knoten = pknoten;
    vorgängerKn = pvorgängerKn;
    double gewicht = pgewicht;
  }
  
  public DijkstraNode(DijkstraNode pDN)
  {
    knoten = pDN.getknoten();
    vorgängerKn = pDN.getvorgängerKn();
    double gewicht = pDN.getgewicht();
  }

  public double getgewicht()
  {
    return gewicht;
  }
  
  public void setgewicht(double pgewicht)
  {
    gewicht = pgewicht;
  }
  
  public GraphNode getvorgängerKn()
  {
    return vorgängerKn;
  }
  
  public void setvorgängerKn(GraphNode pvorgängerKn)
  {
    vorgängerKn = pvorgängerKn;
  }
  
  public GraphNode getknoten()
  {
    return knoten;
  }
  
  public void setknoten(GraphNode pknoten)
  {
    knoten = pknoten;
  }
}

edit: der stil ist recht unschön und der code für mich nur sehr schwer nachvollziehbar. ich würde dir empfehlen, den algorithmus auf einer kleinen instanz schritt für schritt per hand zu debuggen (printf-debugging sollte reichen) und so den fehler zu finden. der dijkstra-algorithmus ist sehr simpel, da passiert ja kaum was.
falls du dazu fragen hast, kannst die ja gerne stellen, aber einfach ne implementierung abladen und den fehler suchen lassen, wird kaum zielführend sein, falls nicht jemand hier gerade sehr große langeweile hat.
 
Zuletzt bearbeitet:
Also, ich habe ein paar Fehler (in der Klasse Dijkstra) schon gefunden und korrigiert:

Code:
public class Dijkstra
{
  private List knoten = new List();
  private List rand = new List();
  private Graph mygraph;
  
  boolean eingefuegt;
  //länge??

  public Dijkstra(Graph pgraph)
  {
    mygraph = pgraph;
  }

  public List starter(GraphNode pstart, GraphNode ziel)
  {
    DijkstraNode start = new DijkstraNode(pstart, 0.0, pstart);
    if(pstart != ziel)
    {
      mygraph.resetMarks();
      kuerzesterWeg(start, ziel);
    }
    //knoten auslesen
    return wegauslesen(pstart, ziel);
  }

  private void kuerzesterWeg(DijkstraNode startKn, GraphNode zielKn)
  {
    while(!mygraph.allNodesMarked())
    {
      startKn.getvorgängerKn().mark();                                            // markiere Vorgängerknoten
      knoten.append(startKn);
      List nachbar = mygraph.getNeighbours(startKn.getknoten());                  // Nachbarliste des Knotens
      nachbar.toFirst();
      while(nachbar.hasAccess())
      {
        if(!((GraphNode) nachbar.getObject()).isMarked())                         // Nachbar unmarkiert?
        {
          double weight = startKn.getgewicht() + gewicht(startKn.getknoten(),(GraphNode) nachbar.getObject());   // Gesamtgewicht
          DijkstraNode DN = new DijkstraNode(((GraphNode) nachbar.getObject()), weight, startKn.getknoten()) ;     // neuer Dijkstranode
          rand = sort_insert(rand,DN);                                            // nach Gewicht sortiert eingefügt in den Rand
          System.out.println("sortiert eingefügt: " + DN.getknoten().getName() + " mit dem Gewicht: " + weight);
          ((GraphNode) nachbar.getObject()).mark();
        }
        nachbar.next();
      }
      rand.toFirst();
      if(rand.hasAccess())
      {
        DijkstraNode helfer = new DijkstraNode((DijkstraNode) rand.getObject());      // DijkstraNode mit dem kleinsten Gewicht aus dem Rand holen
        rand.remove();                                                                // und aus dem Rand löschen
        System.out.println("---------- rekursiver Aufruf: " + helfer.getknoten().getName() + "-----------------");
        kuerzesterWeg(helfer, zielKn);                                                // rekursiver Aufruf
      }
    }
  }

  private List wegauslesen(GraphNode start, GraphNode ziel)
  {
    List weg = new List();
    DijkstraNode dntemp = new DijkstraNode(ziel, 0.0, start);       // ??
    GraphNode gntemp = new GraphNode("");                           // Knoten erstellt
    knoten.toLast();                                                // letztes Element aus Knotenliste
    while(knoten.hasAccess() || ziel == start)                      // Schleife, solange bis die Liste durch ist oder der Zielknoten=Startknoten ist
    {
      dntemp = (DijkstraNode) knoten.getObject();                   // dntemp ist letztes Element aus der Knotenliste
      gntemp = (GraphNode)dntemp.getknoten();
      if(gntemp.getName().equals(ziel.getName()))
      {
        weg.toFirst();
        weg.insert(gntemp);
        ziel = dntemp.getvorgängerKn();
      }
      knoten.remove();
      knoten.toLast();
    }
    return weg;
  }
  
  
  private double gewicht(GraphNode startKn, GraphNode zielKn)
  {
    if(startKn!=zielKn)
    {
      double kantengewicht = mygraph.getEdgeWeight(startKn,zielKn);
      return kantengewicht;
    }
    else
    {
      return 0;
    }
  }
  
  
  private List sort_insert(List prand, DijkstraNode pDN)
  {
    prand.toFirst();            //  springe an den Anfang der Liste
    eingefuegt = false;
    
    if(prand.isEmpty())        // Falls die Liste leer ist
    {
      prand.append(pDN);      System.out.println("1.objekt im rand");
      eingefuegt = true;
    }
    else                      // falls die Liste nicht leer ist
    {

      while ((eingefuegt == false) && (prand.hasAccess()) )
      {
        DijkstraNode aktuellerDN = (DijkstraNode) prand.getObject();
        if(pDN.getknoten().getName().equals(aktuellerDN.getknoten().getName()))
        {
          System.out.println("2 knoten gleich");
          if(pDN.getgewicht() > aktuellerDN.getgewicht())
          {
            eingefuegt = true;     // wenn der schon vorhandene DN ein kleineres Gewicht hat, brauch man nix mehr tun
            System.out.println("vorhandener Knoten hat kleineres Gewicht");
          }
          else
          {
            prand.remove();       // andernfalls: vorhandenen DN löschen und später pDN sortiert einfügen
            System.out.println("vorhandener Knoten gelöscht");
          }
        }
        prand.next();
      }
      
      prand.toFirst();
      
      while ((eingefuegt == false) && (prand.hasAccess()) )  //solange nicht eingefügt und nicht am Ende der Liste
      {
        DijkstraNode aktuellerDN = new DijkstraNode((DijkstraNode) prand.getObject());
        if (pDN.getgewicht() < aktuellerDN.getgewicht())
              //Falls das übergebene Gewicht kleiner als das Aktuelle (in der Liste) ist
        {
          prand.insert(pDN);   //füge die neue DijkstraNode vor der aktuellen ein
          eingefuegt = true;  // schon eingefügt
          System.out.println("neuer DN eingefügt");
        }
        else  //falls das übergebene Gewicht größer als das aktuelle ist
        {
          prand.next();   //gehe eine Position weiter in der Liste
        }
      }
    }
    if(!eingefuegt)        // Falls die Liste leer ist
    {
      prand.append(pDN);
      eingefuegt = true;
    }
    
    System.out.println("Liste wird zurückgegeben mit den Elementen: ");
    prand.toFirst();
    while(prand.hasAccess())
    {
      System.out.println(((DijkstraNode) prand.getObject()).getknoten().getName() +", "+ ((DijkstraNode) prand.getObject()).getgewicht() +", "+ ((DijkstraNode) prand.getObject()).getvorgängerKn().getName());
      prand.next();
    }
    
    return prand;
  }
  
  
}



Code:
public class DijkstraNode
{

  private GraphNode knoten = new GraphNode("");
  private GraphNode vorgängerKn = new GraphNode("");
  private double gewicht=0;
   
  public DijkstraNode(GraphNode pknoten, Double pgewicht, GraphNode pvorgängerKn)
  {
    knoten = pknoten;
    vorgängerKn = pvorgängerKn;
    double gewicht = pgewicht;
  }
  
  public DijkstraNode(DijkstraNode pDN)
  {
    knoten = pDN.getknoten();
    vorgängerKn = pDN.getvorgängerKn();
    double gewicht = pDN.getgewicht();
  }

  public double getgewicht()
  {
    return gewicht;
  }
  
  public void setgewicht(double pgewicht)
  {
    gewicht = pgewicht;
  }
  
  public GraphNode getvorgängerKn()
  {
    return vorgängerKn;
  }
  
  public void setvorgängerKn(GraphNode pvorgängerKn)
  {
    vorgängerKn = pvorgängerKn;
  }
  
  public GraphNode getknoten()
  {
    return knoten;
  }
  
  public void setknoten(GraphNode pknoten)
  {
    knoten = pknoten;
  }
}


Ich kontrolliere die wichtigsten Methoden, indem ich deren Parameter meistens durch Konsole ausgebe ("system.out.println()")... Dadurch kam ich auch auf die gerade behobenen Fehler, sowie darauf, dass das Gesamtgewicht in den DijkstraNodes allesamt 0 ergeben und die Methode "sort_insert" deswegen auch falsch in den Rand/ die Randliste einsortiert.
Außerdem muss ein Fehler in der Methode "wegauslesen" vorkommen, da mir der Compiler genau dort mit seinen "Nullpointer-Exceptions" meckert?!

Falls euch vielleicht der oder die Fehler auffallen, die das Programm nicht funktionieren lassen:
Bitte schreibt, was euch auffällt! :)
 
das ist schon ein guter ansatz. wie gesagt, ich würde es so machen:
mir ne kleine instanz mit 4 oder 5 knoten und ein paar kanten bauen, am besten so, dass der algorithmus immer nur eine wahl für den nächsten knoten hat, in jedem schritt alle variablen ausgeben lassen (marks, gewichte, vorgänger) und das per hand überprüfen. erste stelle suchen, wo was falsch ist, zurückverfolgen bis zum fehler, und so weiter.

edit: die exception kannst ja einfach mal catchen und ausgeben lassen. alternativ mit konsolenausgaben die zeile identifizieren, die die exception schmeißt. es ist aber auch gut möglich, dass da alles richtig implementiert ist und nur die daten, mit der die methode arbeitet, schon kaputt sind (d.h. der / die fehler ist irgendwo vorher).
 
Zuletzt bearbeitet:
Zurück
Oben