Dijkstra实施中的输出不正确

时间:2016-11-28 13:32:26

标签: algorithm

我正在尝试使用邻接列表和优先级队列来实现Dijkstra算法,但是对于某些顶点获取不正确的输出。由于Java中的内置优先级队列中没有decreaseKey方法,因此我添加了新的顶点(与源的更新距离)。谁能告诉我哪里弄错了?我的代码是:

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

1 个答案:

答案 0 :(得分:0)

关闭的是您为visited[i] = true中更新的所有相邻节点设置relaxEdges。 Dijkstra的算法始终只将当前处理的节点设置为已访问,而不是邻居。我猜这就是你输出错误的原因。删除此行,然后在while循环中添加visited[u.getName()] = true

由于您多次向队列添加节点,因此您还应该在while循环中直接测试visited[u.getName()],这样节点就不会被多次处理。

然后,您分配给p[i],但从不使用它。

最后,我建议有一个Edge类,因为将边表示为字符串连接的整数肯定是笨重的。