【问题标题】:Issue in Implementing Dijkstra's algorithm实现 Dijkstra 算法的问题
【发布时间】:2021-04-21 04:15:35
【问题描述】:

我正在尝试解决一个问题,我需要在图中找到 2 个点之间的最大距离。我编写了这段代码来实现 Dijkstra 的算法(显然是通过将最小化更改为最大化),但在某些情况下它似乎不起作用,而且我无法弄清楚未处理的情况。谁能帮我指出我在实现中遗漏了什么或者某些东西本质上是不正确的?

public double maxDistance(int n, int start, int end) {
    
    Map<Integer, List<Integer>> adjacencyList = getAdjacencyList(); // Adj. list in form of HashMap 
    Map<String, Double> distanceMap = getDistanceMap(); // <Edge, Double> (value is distance)
    Queue<Integer> bfsQueue = new LinkedList<>(); // queue to do a BFS
    
    boolean[] visited = new boolean[n];
    double[] distance = new double[n];
    
    bfsQueue.add(start);
    
    while (!bfsQueue.isEmpty()) {
        int node = bfsQueue.poll();
        
        List<Integer> neighbors = adjacencyList.getOrDefault(node, new ArrayList<>());
        for (int neighbor: neighbors) {
            if (visited[neighbor]) continue;
            bfsQueue.add(neighbor);
            double edgeLength = distanceMap.get(new Edge(node, neighbor));
            double newLength = distance[node] + edgeLength;
            if (newLength > distance[neighbor]) {
                distance[neighbor] = newLength;
            }
        }
        visited[node] = true;
    }

    return distance[end];
}

【问题讨论】:

  • bfsQueue 应该是一个优先级队列,或者其他排序的数据结构,而不仅仅是一个 LinkedList。
  • 另外,不知道例如的实现Edge,很难判断 distanceMap.get(new Edge(...)) 是否按预期工作。您是否正确覆盖了Edge.equals()Edge.hashCode()
  • 请举例说明它不起作用。
  • @cello 我认为这可能是问题所在。排序后的数据结构在这里有何不同,请您详细说明!
  • @Henry 我正在用手机打字,所以我会在我在家时发布示例。

标签: java dijkstra


【解决方案1】:

首先,Dijkstra 算法找到最短路径,因此它应该是minDistance,而不是maxDistance

接下来,要实现广度优先搜索,您需要一个排序的数据结构。您的bfsQueue 目前只是一个LinkedList。使用链表,您可以按插入顺序遍历项目。但是在 Dijkstra 的算法中,总是处理下一个最近的邻居是很重要的。因此通常使用优先级队列来实现。

举个例子,为什么这会有所不同:您想要从 A 到 B 的图像。有两条路线可用,一条由两条边组成的长路线,一条由 4 条边组成的较短路线。在您的情况下,您基本上通过自开始以来的边数而不是距离来扩展图形。所以你会首先找到由两条边组成的路线,即使这是较慢的一条。

如果您使用PriorityQueue,请注意减少邻居的距离/优先级(if (newLength &gt; distance[neighbor]) { distance[neighbor] = newLength; })将不起作用,因为优先级队列不会自动重新排序。您必须首先从优先级队列中删除邻居,更新距离,然后将其重新插入优先级队列,以便将其排序到正确的位置。

【讨论】:

  • 谢谢!我正在尝试解决成本节约问题(最大化问题),所以我只想通过添加适当的变化来使用此算法。 Wrt 排序,我知道它是一个贪心算法,但如果我要检查所有节点,那么我进入哪个顺序有什么关系?那是我不清楚的部分。
  • 每个顶点只访问一次 (--> boolean[] visited),所以它必须是一种贪婪的方式,否则你只会在你的图中得到一个随机路径——或者你会以某种方式重置访问标志,但它绝对不再是 Dijkstra 的算法。
  • 明白了!我想我明白了,让我试一试,然后回来标记这个答案。谢谢!
  • PrirorityQueue 完美运行,并且作为一种贪心算法是有意义的,因此队列中选择的下一个节点始终是具有最高优先级的节点。感谢您的帮助!
猜你喜欢
  • 2012-11-25
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-20
  • 1970-01-01
相关资源
最近更新 更多