2017-10-16 1 views
0

Dijkstraのアルゴリズムを変更して、最小値を持つすべてのパスを表示しようとしています。そこで、以前の頂点のリストを使用することにしました。そして、パスが最小値で以前のものと同じかどうかをチェックするif節を追加しました。私は前の頂点を現在のものの親として追加します。 問題は、StackOverflowエラーが発生していて、何が原因なのかわかりません。 これは私のコードです 以下のコードの目的は、グラフ内のすべての頂点についてDijkstraを計算し、見つかった最小のパスに頂点が現れる回数を計算し、それらのすべてを降順で表示することです。Dijkstraを変更して等しい値のパスを保存する - StackOverflowエラー

public class Dijkstra { 

    public static final Map<String, Integer> ordem = new HashMap<>(); 

    public static void main(String[] args) throws FileNotFoundException, IOException { 
     List<Graph.Edge> edges = new ArrayList<>(); 

     try { 
      FileReader arq = new FileReader("input.txt"); 
      BufferedReader fw = new BufferedReader(arq); 
      String linha = ""; 
      while (fw.ready()) { 
       linha = fw.readLine(); 
       if (!linha.equals("0,0,0")) { 
        String parts[] = linha.split(","); 
        ordem.put(parts[0], 0); 
        ordem.put(parts[1], 0); 
        Graph.Edge a = new Graph.Edge(parts[0], parts[1], 100 - Integer.parseInt(parts[2])); 
        edges.add(a); 
       } else { 
        break; 
       } 

      } 
      fw.close(); 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
     Graph g = new Graph(edges); 

     for (int i = 0; i < 5; i++) { 
      g.dijkstra(String.valueOf(i)); 
      g.printAllPaths(); 
     } 

     Object[] a = ordem.entrySet().toArray(); 
     Arrays.sort(a, new Comparator() { 
      public int compare(Object o1, Object o2) { 
       return ((Map.Entry<String, Integer>) o2).getValue() 
         .compareTo(((Map.Entry<String, Integer>) o1).getValue()); 
      } 
     }); 
     for (Object e : a) { 
      System.out.print(((Map.Entry<String, Integer>) e).getKey() + " "); 
     } 
     System.out.println("\n"); 
    } 
} 

class Graph { 

    private final Map<String, Vertex> graph; 

    public static class Edge { 

     public final String v1, v2; 
     public final int dist; 

     public Edge(String v1, String v2, int dist) { 
      this.v1 = v1; 
      this.v2 = v2; 
      this.dist = dist; 
     } 
    } 

    public static class Vertex implements Comparable<Vertex> { 

     public final String name; 
     public int dist = Integer.MAX_VALUE; 
     public List<Vertex> previous = new ArrayList<>(); 
     public final Map<Vertex, Integer> neighbours = new HashMap<>(); 

     public Vertex(String name) { 
      this.name = name; 
     } 

     private void printPath() { 
      if (this == this.previous) { 
      } else if (this.previous == null) { 
      } else { 
       //This is where I am getting the error 
       for (int i = 0; i<this.previous.size(); i++){ 
       this.previous.get(i).printPath(); 
       Dijkstra.ordem.replace(this.name, Dijkstra.ordem.get(this.name) + 1); 
      } 

      } 
     } 

     public int compareTo(Vertex other) { 
      if (dist == other.dist) { 
       return name.compareTo(other.name); 
      } 

      return Integer.compare(dist, other.dist); 
     } 

     @Override 
     public String toString() { 
      return "(" + name + ", " + dist + ")"; 
     } 
    } 

    public Graph(List<Graph.Edge> edges) { 
     graph = new HashMap<>(edges.size()); 

     for (Edge e : edges) { 
      if (!graph.containsKey(e.v1)) { 
       graph.put(e.v1, new Vertex(e.v1)); 
      } 
      if (!graph.containsKey(e.v2)) { 
       graph.put(e.v2, new Vertex(e.v2)); 
      } 
     } 

     for (Edge e : edges) { 
      graph.get(e.v1).neighbours.put(graph.get(e.v2), e.dist); 
      graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist); 
     } 
    } 


    public void dijkstra(String startName) { 
     if (!graph.containsKey(startName)) { 
      System.err.printf("Graph doesn't contain start vertex \"%s\"\n", startName); 
      return; 
     } 
     final Vertex source = graph.get(startName); 
     NavigableSet<Vertex> q = new TreeSet<>(); 

     // Inicializacao dos vertices 
     for (Vertex v : graph.values()) { 
      //v.previous = v == source ? list : null; 
      if (v == source) { 
       v.previous.add(source); 
      } else { 
       v.previous = new ArrayList<>(); 
      } 
      v.dist = v == source ? 0 : Integer.MAX_VALUE; 
      q.add(v); 
     } 

     dijkstra(q); 
    } 

    private void dijkstra(final NavigableSet<Vertex> q) { 
     Vertex u, v; 
     while (!q.isEmpty()) { 

      u = q.pollFirst(); 
      if (u.dist == Integer.MAX_VALUE) { 
      } 
      for (Map.Entry<Vertex, Integer> a : u.neighbours.entrySet()) { 
       v = a.getKey(); 

       final int alternateDist = u.dist + a.getValue(); 
       if (alternateDist < v.dist) { 
        q.remove(v); 
        v.dist = alternateDist; 
        v.previous.add(u); 
        q.add(v); 
       } else if(alternateDist == v.dist) { 
        v.previous.add(u); 
       } 
      } 
     } 
    } 


    public void printPath(String endName) { 
     if (!graph.containsKey(endName)) { 
      System.err.printf("Graph doesn't contain end vertex \"%s\"\n", endName); 
      return; 
     } 

     graph.get(endName).printPath(); 
     //System.out.println(); 
    } 

    public void printAllPaths() { 
     for (Vertex v : graph.values()) { 
      v.printPath(); 
     } 
    } 
} 

これはエラーです:

Exception in thread "main" java.lang.StackOverflowError 
    at Graph$Vertex.printPath(Dijkstra.java:117) 
    at Graph$Vertex.printPath(Dijkstra.java:118) 
+0

Whoah、それは多くのコードです。あなたは本当に人々にそれを漁ってもらうことを期待していますか? 'StackOverflowException'は通常、無限の再帰があるときに発生します。単に:void a(){a(); } '。 –

+0

小さな(たとえば3x3または4x4)グリッドのパスを見つけたら、それを取得しますか?そのスケールでは、すべてのステップを出力することができますし、そうすることでアルゴリズムが間違っている場所を検出することができます。 – GolezTrol

+0

返信いただきありがとうございます!私はちょうど私がエラーを取得しているforループのコメントを追加しました。 @GolezTrol私は5つの頂点と5つのエッジを持つグラフでコードをテストしています。 –

答えて

0

エラーメッセージがすでに示唆したよう:あなたのダイクストラは問題ではありません。 問題は、printPath()自体を呼び出すことです。

多分犯人はあなたがList<Vertex> previousVertex thisを比較

if (this == this.previous) {} ... 

です。おそらくチェックしたいかもしれません

if (this == this.previous.get(this.previous.size() - 1)) {} ... 

あなたのコードが(1)長すぎて(2)自己完結型ではない(少なくとも "input.txt"がない)ため、私はこれをテストしませんでした。

+0

返信いただきありがとうございます!各行はある 0,1,70 1,2,50 2,3,88 3,4,20 4,2,5 0,0,0 :INPUT.TXTはこのようなものになるだろう(第1および第2の属性は頂点であり、第3の属性は辺の重みです。すべての辺はファイルの異なる行になければなりません)。私はあなたの提案を試みるつもりです。 –

関連する問題