繁体   English   中英

如何实现Dijkstra算法以找到Java中的最短路径

[英]How to implement Dijkstra's Algorithm to find the shortest path in Java

我对做什么绝对感到困惑。 我正在尝试从Wikipedia在Dijkstra的具有优先级队列的伪代码中编写代码,但是我很难进行调整以适应我需要找到的内容。 到目前为止,这是我的代码(不完整),非常感谢您的帮助。

public int doDijkstras (String startVertexName, String endVertexName, ArrayList< String > shortestPath) {
        PriorityQueue<QEntry> q = new PriorityQueue<QEntry>();
        int cost = 0;
        int newCost;
        QEntry pred = null;
        for (String s : this.getVertices()) {
            if (!s.equals(startVertexName)) {
                cost = Integer.MAX_VALUE;
                pred = null;
            }
            q.add(new QEntry(s, cost, pred, adjacencyMap.get(s)));
        }

        while (!q.isEmpty()) {
            QEntry curr = getMin(q);
            for (String s : curr.adj.keySet()) {
                newCost = curr.cost + this.getCost(curr.name, s);
                QEntry v = this.getVert(q, s);
                if (newCost < v.cost) {
                    v.cost = newCost;
                    v.pred = curr;
                    if (!q.contains(curr)) {
                        q.add(curr);
                    }
                }
            }
        }
    }

    private QEntry getMin(PriorityQueue<QEntry> q) {
        QEntry min = q.peek();
        for (QEntry temp : q) {
            if (min.cost > temp.cost) {
                min = temp;
            }
        }
        return min;
    }

    private QEntry getVert(PriorityQueue<QEntry> q, String s) {
        for (QEntry temp : q) {
            if (temp.name.equals(s)) {
                return temp;
            }
        }
        return null;
    }

    class QEntry {
        String name;
        int cost;
        QEntry pred;
        TreeMap<String, Integer> adj;

        public QEntry(String name, int cost, QEntry pred, TreeMap<String, Integer> adj) {
            this.name = name;
            this.cost = cost;
            this.adj = adj;
            this.pred = pred;
        }
    }

您正在忽略算法的重要部分:何时停止。

Wikipedia上的伪代码用于Dijkstra算法的变体,该算法计算从起始节点到与其连接的每个节点的最短路径。 大伪代码块之后的注释说明了如何修改算法以仅查找到特定目标的路径,然后是较短的块,说明如何提取路径。

但是,用英语来说,在处理优先级队列时,需要注意目标元素是否被选中。 无论何时(如果有的话),您都知道,找到它的最短路径就是将成本记录在目标队列条目中并由该条目及其前身链(以相反顺序)表示的路径。 通过遍历前辈链来填充路径列表,然后返回目标队列条目中记录的值。

但是请注意,在您的代码中,如果起始顶点和目标顶点未在图中连接(包括目标根本不在图中),最终将耗尽队列并跌出底部。而while循环却从未达到目标。 您必须决定如何处理路径列表以及在这种情况下要返回什么。

还要注意,您的代码似乎有几个错误,其中包括:

  • 如果起始顶点名称不是this.getVertices()的迭代顺序中的第一个,则其队列条目将不会使用成本0进行初始化,并且不可能是从队列中选择的第一个元素。
  • 如果指定的起始顶点根本不在图形中,则您的代码将运行,并可能发出路径,但在这种情况下其输出是虚假的。
  • 您的队列元素(类型QEntry )没有自然顺序。 要创建其元素具有此类的PriorityQueue ,必须提供一个Comparator来定义其相对优先级。
  • 您将优先级队列用作普通列表。 这本身不会使您的代码产生错误的结果,但是增加其渐近复杂性。
  • 但是请注意,如果将标准PriorityQueue 用作优先级队列,则绝不能以可能改变其相对于任何其他排队对象顺序的方式修改排队对象。 而是先将其从队列中删除,然后对其进行修改,然后再次使其入队。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM