当前位置: 首页 > 知识库问答 >
问题:

无法找到使用Dijkstra算法的最短路径?

鄢博简
2023-03-14

我试图找到shrotest路径之间的节点az使用Dijkstra算法,但每次它给我错误的响应。

下面是我的代码-

public class DijkstraAlgorithm {

    // Am I mapping this correctly by looking at the below graph?
    // looks to me I got this wrong?
    private static final Graph.Edge[] GRAPH = { 
        new Graph.Edge("a", "g", 8), 
        new Graph.Edge("a", "b", 1), 
        new Graph.Edge("a", "e", 1), 
        new Graph.Edge("b", "c", 1), 
        new Graph.Edge("b", "e", 1),
        new Graph.Edge("b", "f", 2),
        new Graph.Edge("c", "g", 1),
        new Graph.Edge("c", "d", 1),
        new Graph.Edge("d", "f", 1),
        new Graph.Edge("d", "z", 1),
        new Graph.Edge("e", "f", 4),
        new Graph.Edge("f", "z", 4),
        new Graph.Edge("g", "z", 2),
    };

    private static final String START = "a";
    private static final String END = "z";

    public static void main(String[] args) {
        Graph g = new Graph(GRAPH);
        g.dijkstra(START);
        //  print the shortest path using Dijkstra algorithm
        g.printPath(END);
        //g.printAllPaths();
    }
}

class Graph {
    private final Map<String, Vertex> graph; // mapping of vertex names to Vertex objects, built from a set of Edges

    /** One edge of the graph (only used by Graph constructor) */
    public static class Edge {
        public final String v1, v2;
        public final int dist;

        public Edge(String v1, String v2, int dist) {
            this.v1 = v1;
            this.v2 = v2;
            this.dist = dist;
        }
    }

    /** One vertex of the graph, complete with mappings to neighbouring vertices */
    public static class Vertex implements Comparable<Vertex> {
        public final String name;
        public int dist = Integer.MAX_VALUE; // MAX_VALUE assumed to be infinity
        public Vertex previous = null;
        public final Map<Vertex, Integer> neighbours = new HashMap<Vertex, Integer>();

        public Vertex(String name) {
            this.name = name;
        }

        private void printPath() {
            if (this == this.previous) {
                System.out.printf("%s", this.name);
            } else if (this.previous == null) {
                System.out.printf("%s(unreached)", this.name);
            } else {
                this.previous.printPath();
                System.out.printf(" -> %s(%d)", this.name, this.dist);
            }
        }

        public int compareTo(Vertex other) {
            return Integer.compare(dist, other.dist);
        }
    }

    /** Builds a graph from a set of edges */
    public Graph(Edge[] edges) {
        graph = new HashMap<String, Vertex>(edges.length);

        //one pass to find all vertices
        for (Edge e : edges) {
            if (!graph.containsKey(e.v1))
                graph.put(e.v1, new Vertex(e.v1));
            if (!graph.containsKey(e.v2))
                graph.put(e.v2, new Vertex(e.v2));
        }

        //another pass to set neighbouring vertices
        for (Edge e : edges) {
            graph.get(e.v1).neighbours.put(graph.get(e.v2), e.dist);
            graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist); // also do this for an undirected graph
        }
    }

    /** Runs dijkstra using a specified source vertex */
    public void dijkstra(String startName) {
        if (!graph.containsKey(startName)) {
            System.err.printf("Graph doesn't contain start vertex \"%s\"\n", startName);
            return;
        }
        final Vertex source = graph.get(startName);
        NavigableSet<Vertex> q = new TreeSet<Vertex>();

        // set-up vertices
        for (Vertex v : graph.values()) {
            v.previous = v == source ? source : null;
            v.dist = v == source ? 0 : Integer.MAX_VALUE;
            q.add(v);
        }

        dijkstra(q);
    }

    /** Implementation of dijkstra's algorithm using a binary heap. */
    private void dijkstra(final NavigableSet<Vertex> q) {
        Vertex u, v;
        while (!q.isEmpty()) {

            u = q.pollFirst(); // vertex with shortest distance (first iteration will return source)
            if (u.dist == Integer.MAX_VALUE)
                break; // we can ignore u (and any other remaining vertices) since they are unreachable

            //look at distances to each neighbour
            for (Map.Entry<Vertex, Integer> a : u.neighbours.entrySet()) {
                v = a.getKey(); //the neighbour in this iteration

                final int alternateDist = u.dist + a.getValue();
                if (alternateDist < v.dist) { // shorter path to neighbour found
                    q.remove(v);
                    v.dist = alternateDist;
                    v.previous = u;
                    q.add(v);
                }
            }
        }
    }

    /** Prints a path from the source to the specified vertex */
    public void printPath(String endName) {
        if (!graph.containsKey(endName)) {
            System.err.printf("Graph doesn't contain end vertex \"%s\"\n", endName);
            return;
        }

        graph.get(endName).printPath();
        System.out.println();
    }

    /** Prints the path from the source to every vertex (output order is not guaranteed) */
    public void printAllPaths() {
        for (Vertex v : graph.values()) {
            v.printPath();
            System.out.println();
        }
    }
}

根据计算,从节点A到节点Z的最短路径是ABCDZ,但我得到A-

我猜,我在上面代码中对图形数据值的映射是错误的?有没有更好的方法来表示我的图形?

我上面的代码有什么错误吗?


共有1个答案

丌官寒
2023-03-14

问题在于您的队列结构。它基于树集,树集使用比较函数来排序。不幸的是,树集的每个关键点只能有一个值,因此,如果两个元素比较相等(例如,具有MAXINT distance的所有顶点将比较相等),它们将被有效删除。

您可以通过打印队列的长度来看到这一点,您可以插入8个元素,但它的大小只有2。

一个简单的解决方法是:

    public int compareTo(Vertex other) {
        if (dist==other.dist)
            return name.compareTo(other.name);
        return Integer.compare(dist, other.dist);
    }

这将阻止将不同顶点作为相等顶点进行比较。

 类似资料:
  • 我已经从Cormen的第三版参考“算法介绍”中找到的伪代码中实现了Dijkstra算法,用于单源最短路径问题。 我的实现是在python上使用链接列表在邻接列表表示中表示图形。这意味着节点列表是一个链接列表,每个节点都有一个链接列表来表示每个节点的边缘。此外,我没有实现或使用任何二进制堆或斐波那契堆作为算法所需的最小优先级队列,因此当过程需要提取与源距离最小的下一个节点时,我在节点链表内搜索O(V

  • 最短路径问题的Dijkstra算法 是由荷兰计算机科学家艾兹赫尔·戴克斯特拉提出。迪科斯彻算法使用了广度优先搜索解决非负权有向图的单源最短路径问题,算法最终得到一个最短路径树。该算法常用于路由算法或者作为其他图算法的一个子模块。 这个算法的python实现途径很多,网上能够发现不少。这里推荐一个我在网上看到的,本来打算自己写,看了这个,决定自己不写了,因为他的已经太好了。 解决(Python) #

  • 本文向大家介绍java实现Dijkstra最短路径算法,包括了java实现Dijkstra最短路径算法的使用技巧和注意事项,需要的朋友参考一下 任务描述:在一个无向图中,获取起始节点到所有其他节点的最短路径描述 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。 Dijkstra一般的表述

  • 本文向大家介绍java实现最短路径算法之Dijkstra算法,包括了java实现最短路径算法之Dijkstra算法的使用技巧和注意事项,需要的朋友参考一下 前言 Dijkstra算法是最短路径算法中为人熟知的一种,是单起点全路径算法。该算法被称为是“贪心算法”的成功典范。本文接下来将尝试以最通俗的语言来介绍这个伟大的算法,并赋予java实现代码。 一、知识准备: 1、表示图的数据结构 用于存储图的

  • 本文向大家介绍java实现dijkstra最短路径寻路算法,包括了java实现dijkstra最短路径寻路算法的使用技巧和注意事项,需要的朋友参考一下 【引用】迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。  它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。 基本思想 通过Dijkstra计算图G中的最短路径时,需要指

  • 我知道Dijkstra的算法实际上是使用斐波那契堆实现的。但是,它也可以使用红色的黑树来实现,并且仍然具有O(m log n)的最坏情况运行时间吗?