【问题标题】:Dijkstras Algorithm implementationDijkstra 算法实现
【发布时间】:2022-01-05 15:19:12
【问题描述】:

我尝试了 Dijkstras 算法,但在 2 种实现之间感到困惑,一个跟踪访问过的节点(代码 1),另一个不跟踪(代码 2)。

代码1:

    dis[S] = 0;  //S is source
    vis[S] = 1;
    
    PriorityQueue<Node> queue = new PriorityQueue<>();
    queue.offer(new Node(S, 0));
    
    while(!queue.isEmpty()){
        
        Node node = queue.poll();
        
        int u = node.v;
        vis[u] = 1;
        
        for(Node n: adj1.get(u)){
            int v = n.v;
            int w = n.w;
            
            if(vis[v] == 0){
                if(dis[u]+w < dis[v]){
                    dis[v] = dis[u]+w;
                   
                }
                 queue.offer(n);
                
            }  
        }
        
    }
    `

代码2:

    dis[S] = 0;
    //vis[S] = 1;
    
    PriorityQueue<Node> queue = new PriorityQueue<>();
    queue.offer(new Node(S, 0));
    
    while(!queue.isEmpty()){
        
        Node node = queue.poll();
        
        int u = node.v;
        // vis[u] = 1;
        
        for(Node n: adj1.get(u)){
            int v = n.v;
            int w = n.w;
            
            // if(vis[v] == 0){
                if(dis[u]+w < dis[v]){
                    dis[v] = dis[u]+w;
                    queue.offer(n);
                   
                }
                 
                
            // }  
        }
        
    }

代码 1 未通过某些测试用例 代码 2 通过所有测试用例。任何人都可以解释为什么代码 1 失败,就像我缺少的边缘情况一样。

【问题讨论】:

标签: java algorithm data-structures graph dijkstra


【解决方案1】:

您的两个实现都不正确。 “代码 2”可能有效,但可能很慢。

这两种实现中最明显的问题是您的优先级队列充满了。在 Dijkstra 算法中,队列按当前最佳发现成本顶点进行排序。您的优先级队列无法正确执行此操作。

我猜你实际上是按 weight 排序边。会以错误的顺序为您提供顶点,这可能会导致“代码 1”由于访问检查而失败。

下一个问题是visited check的实现。如果您没有使用支持decrease_key() 操作的堆,则每次减少权重时都必须将顶点添加到队列中,因此它可能会多次进入队列。当它从队列中出来时,您将知道它的最佳成本,因此您可以通过在看到队列中的其他实例时忽略它们来节省时间。

您确实使用访问过的检查来确保您只添加一次顶点,因为这样就无法减少键并且您的实现被破坏了。

正确的实现如下所示:

// initialize dis to max value
for (int i=0; i<dis.length; ++i) {
    dis[i] = Integer.MAX_VALUE;
}
dis[S] = 0;  //S is source
// Note that S isn't scanned yet, so vis[S] == 0

PriorityQueue<PriorityNode> queue = new PriorityQueue<>();
queue.offer(new PriorityNode(S, 0));

while(!queue.isEmpty()){
    
    PriorityNode node = queue.poll(); 
    int u = node.vertex;

    if (vis[u] != 0) {
        // already resolved this vertex
        continue;
    }

    vis[u] = 1;
    
    for(Edge n: adj1.get(u)){
        int v = n.v;
        int w = n.w;
        
        if(dis[u]+w < dis[v]){
            dis[v] = dis[u]+w;
            // We found a better cost for v
            queue.offer(new PriorityNode(v, dis[v]));
        }
    }        
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 2014-06-23
    • 2019-04-02
    • 2011-09-13
    • 2015-02-05
    • 1970-01-01
    相关资源
    最近更新 更多