2016-11-28 5 views
0

隣接リストと優先度キューを使用してDijkstraのアルゴリズムを実装しようとしましたが、一部の頂点で正しく出力されません。 Javaのinbuilt優先順位キューにはreduceKeyメソッドがないので、新しい頂点(ソースから更新された距離を持つ)を追加しています。誰かが私が間違っているとアドバイスできますか?私のコードは次のとおりです。オフになっているDijkstraの実装で不正な出力が発生しました

class Graph3 { 
    private int V; 
    private ArrayList<Integer> adj []; 
    Map<String, Integer> weight; //for O(1) lookup of edge weight 
    PriorityQueue<Vertex> minHeap; 
    int d []; 
    int p[]; 
    boolean visited []; 
    Graph3(int n) { 
     this.V = n; 
     adj = new ArrayList[n]; 
     for(int i=0; i<n; i++) { 
      adj[i] = new ArrayList<Integer>(); 
     } 
     weight = new HashMap<String, Integer>(); 
     minHeap = new PriorityQueue<Vertex>(n, new Vertex()); 
     visited = new boolean[n]; 
     Arrays.fill(visited, false); 
     p = new int[n]; 
     Arrays.fill(p, -1); 
     d = new int[n]; 
     Arrays.fill(d,Integer.MAX_VALUE); 
    } 
    public void addEdge(int a, int b, int w) { 
     adj[a].add(b); 
     weight.put(a+","+b,w); //cost of edge(a,b) 
    } 

    public void calculateShortest(int source) { 
     d[source] = 0; 
     visited[source] = true; 
     for(int i=0; i<V; i++) minHeap.offer(new Vertex(i,d[i])); 
     while(!minHeap.isEmpty()) { 
      Vertex u = minHeap.poll(); 
      relaxEdges(u); //relax all outgoing edges of u 
     } 
     for(int i=0; i<d.length; i++) { 
      System.out.println("Shortest path from "+source+" to vertex "+i+" = "+d[i]); 
     } 
    } 

    public void relaxEdges(Vertex u) {  
     for(int i: adj[u.getName()]) { 
      if(!visited[i]) { 
       int alt = d[u.getName()] + weight.get(u.getName()+","+i); 
       if(d[i] > alt) { 
        d[i] = alt; 
        Vertex temp = new Vertex(i,d[i]); 
        minHeap.offer(temp); 
        p[i] = u.getName(); 
        visited[i] = true; 
       } 
      } 
     } 
    } 
} 
//to be used for binding every vertex with dval for use in PQ 
class Vertex implements Comparator<Vertex> { 
    int name; 
    int dval; //current min distance from source 
    public Vertex() { 

    } 
    public Vertex(int name, int dval) { 
     this.name = name; 
     this.dval = dval; 
    } 
    public int getName() { 
     return name; 
    } 
    public void setName(int name) { 
     this.name = name; 
    } 
    public int getDval() { 
     return dval; 
    } 
    public void setDval(int dval) { 
     this.dval = dval; 
    } 
    public int compare(Vertex a, Vertex b) { 
     return (a.dval - b.dval); 
    } 
} 
public class DijkstraShortestPath { 

    public static void main(String args []) { 
     Graph3 g = new Graph3(9); 
     g.addEdge(0, 1, 4); 
     g.addEdge(0, 7, 8); 
     g.addEdge(1, 2, 8); 
     g.addEdge(1, 7, 11); 
     g.addEdge(2, 3, 7); 
     g.addEdge(2, 8, 2); 
     g.addEdge(2, 5, 4); 
     g.addEdge(3, 4, 9); 
     g.addEdge(3, 5, 14); 
     g.addEdge(4, 5, 10); 
     g.addEdge(5, 6, 2); 
     g.addEdge(6, 7, 1); 
     g.addEdge(6, 8, 6); 
     g.addEdge(7, 8, 7); 

     g.calculateShortest(0); 
    } 
} 
**My Output :** 
Shortest path from 0 to vertex 0 = 0 
Shortest path from 0 to vertex 1 = 4 
Shortest path from 0 to vertex 2 = 12 
Shortest path from 0 to vertex 3 = 19 
Shortest path from 0 to vertex 4 = 28 
Shortest path from 0 to vertex 5 = 16 
Shortest path from 0 to vertex 6 = 18 
Shortest path from 0 to vertex 7 = 8 
Shortest path from 0 to vertex 8 = 15 
**Correct Output :** 
Shortest path from 0 to vertex 0 = 0 
Shortest path from 0 to vertex 1 = 4 
Shortest path from 0 to vertex 2 = 12 
Shortest path from 0 to vertex 3 = 19 
Shortest path from 0 to vertex 4 = 21 
Shortest path from 0 to vertex 5 = 11 
Shortest path from 0 to vertex 6 = 9 
Shortest path from 0 to vertex 7 = 8 
Shortest path from 0 to vertex 8 = 14 

答えて

0

何かがあなたがrelaxEdgesに更新されますすべての隣接ノードに対してvisited[i] = trueを設定することです。 Dijkstraのアルゴリズムは常に、現在処理されているノードを訪問先に設定するだけで、隣人は設定しません。私はこれがあなたが間違った出力を得る理由だと推測します。この行を削除し、whileループにvisited[u.getName()] = trueを追加してください。

ノードを複数回キューに追加するので、whileループでvisited[u.getName()]に対して直接テストして、ノードが複数回処理されないようにする必要があります。

次に、p[i]に割り当てますが、決して使用しないでください。

最後に、文字列連結された整数としてエッジを表現するのが確実に難しいため、Edgeクラスを使用するようアドバイスします。

関連する問題