JAVA-使用Dijkstra算法找到2个顶点之间的最短路径

时间:2018-11-18 05:18:53

标签: java

所以我正在做一个数学项目,而不是计算机科学项目,但是我想使用代码来帮助收集数据。为此,我想使用Dijkstra的算法并计算出要获得答案之前必须走多少个边。但是我找不到适用于我的图形的任何现有代码。

package mathematicsia;

import java.util.PriorityQueue;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;

class Vertex implements Comparable<Vertex>
{
    public final String name;
    public Edge[] adjacencies;
    public double minDistance = Double.POSITIVE_INFINITY;
    public Vertex previous;
    public Vertex(String argName) { name = argName; }
    public String toString() { return name; }
    public int compareTo(Vertex other)
    {
        return Double.compare(minDistance, other.minDistance);
    }

}


class Edge
{
    public final Vertex target;
    public final double weight;
    public Edge(Vertex argTarget, double argWeight)
    { target = argTarget; weight = argWeight; }
}

public class DijkstrasAlgorithm
{
    public static void computePaths(Vertex source)
    {
        source.minDistance = 0.;
        PriorityQueue<Vertex> vertexQueue = new PriorityQueue<Vertex>();
        vertexQueue.add(source);

        while (!vertexQueue.isEmpty()) {
            Vertex u = vertexQueue.poll();

            // Visit each edge exiting u
            for (Edge e : u.adjacencies)
            {
                Vertex v = e.target;
                double weight = e.weight;
                double distanceThroughU = u.minDistance + weight;
                if (distanceThroughU < v.minDistance) {
                    vertexQueue.remove(v);

                    v.minDistance = distanceThroughU ;
                    v.previous = u;
                    vertexQueue.add(v);
                }
            }
        }
    }

    public static List<Vertex> getShortestPathTo(Vertex target)
    {
        List<Vertex> path = new ArrayList<Vertex>();
        for (Vertex vertex = target; vertex != null; vertex = vertex.previous)
            path.add(vertex);

        Collections.reverse(path);
        return path;
    }

    public static void main(String[] args)
    {
        // mark all the vertices 
        Vertex P = new Vertex("P");
        Vertex L = new Vertex("L");
        Vertex E = new Vertex("E");

        Vertex B4 = new Vertex("B4"); //Bridge Level 4
        Vertex B5 = new Vertex("B5"); //Bridge Level 5

        Vertex A2 = new Vertex("A2"); //Stairs A
        Vertex A3 = new Vertex("A3");
        Vertex A4 = new Vertex("A4");
        Vertex A5 = new Vertex("A5");
        Vertex A6 = new Vertex("A6");

        Vertex C2 = new Vertex("C2"); //Stairs C
        Vertex C3 = new Vertex("C3");
        Vertex C4 = new Vertex("C4");
        Vertex C5 = new Vertex("C5");
        Vertex C6 = new Vertex("C6");

        // set the edges and weight
        L.adjacencies = new Edge[]{ new Edge(A2, 83) }; //A
        L.adjacencies = new Edge[]{ new Edge(B4, 90) }; //B
        L.adjacencies = new Edge[]{ new Edge(B5, 130) }; //C
        L.adjacencies = new Edge[]{ new Edge(C2,86 ) }; //D

        B4.adjacencies = new Edge[]{ new Edge(C4, 33) }; //E
        B4.adjacencies = new Edge[]{ new Edge(A4,59 ) }; //F

        A2.adjacencies = new Edge[]{ new Edge(C2, 97) }; //G
        A3.adjacencies = new Edge[]{ new Edge(C3,70 ) }; //H
        A4.adjacencies = new Edge[]{ new Edge(C4,71 ) }; //I

        A2.adjacencies = new Edge[]{ new Edge(A3,15 ) }; //J
        A3.adjacencies = new Edge[]{ new Edge(A4,15 ) }; //K
        A4.adjacencies = new Edge[]{ new Edge(A5,15 ) }; //L
        A5.adjacencies = new Edge[]{ new Edge(A6, 15) }; //M
        A6.adjacencies = new Edge[]{ new Edge(C6, 75) }; //N

        P.adjacencies = new Edge[]{ new Edge(A6, 27) }; //O
        E.adjacencies = new Edge[]{ new Edge(A3,85 ) }; //P
        P.adjacencies = new Edge[]{ new Edge(C6, 97) }; //Q
        E.adjacencies = new Edge[]{ new Edge(C3, 25) }; //R

        B5.adjacencies = new Edge[]{ new Edge(C5,33 ) }; //S
        B5.adjacencies = new Edge[]{ new Edge(A5, 59) }; //T

        C5.adjacencies = new Edge[]{ new Edge(C4, 15) }; //U
        C4.adjacencies = new Edge[]{ new Edge(C3, 15) }; //V
        C3.adjacencies = new Edge[]{ new Edge(C2,24 ) }; //W
        C6.adjacencies = new Edge[]{ new Edge(C5, 15) }; //X

        P.adjacencies = new Edge[]{ new Edge(C6,73 ) }; //Y 
        A5.adjacencies = new Edge[]{ new Edge(C5, 75) }; //Z



        computePaths(L); // run Dijkstra
        System.out.println("Distance to " + P + ": " + P.minDistance);
        List<Vertex> path = getShortestPathTo(P);
        System.out.println("Path: " + path);
    }
}

这不起作用,因为它在我尝试运行时给我一个错误,请帮助!

1 个答案:

答案 0 :(得分:0)

让我们从您的Vertex类开始。您无法同时存储两个地形信息的最佳设计:

  • 名称
  • 邻接

关于遍历的可变信息:

  • minDistance
  • 上一个

让我们首先“净化”顶点以仅表示地形信息。另外,让我们实现hashCode()和equals(),以便可以在字典中使用它。

class Vertex
{
    public final String name;
    public Edge[] adjacencies;

    public Vertex(String argName) { name = argName; }
    public String toString() { return name; }
    public int equals(Vertex other) {
        return this.name.compareTo(other.name);
    }
    public int hashCode() {
        return this.name.hashCode();
    }
}

然后让结果类保存路径集:

class Path {
    HashMap<Vertex, Integer> distances = new HashMap<>();
    HashMap<Vertex, Vertex> backtrack = new HashMap<>(); 
}

现在,我们可以实现Dijkstras。我对您的实现进行了一些修改,以使其在功能上与wikipedia entry相匹配。这样,您就可以跟随他们的动画了。

public Path computePaths(Vertex source)
{
    Path p = new Path();
    Set<Vertex> visited = new HashSet<>();
    distances.put(source, 0); // Distance from source to source

    Queue<Vertex> vertexQueue = new LinkedList<Vertex>();
    vertexQueue.add(source);
    visited.add(source);

    while (!vertexQueue.isEmpty()) {
        Vertex u = vertexQueue.remove();

        // Visit each edge exiting u
        for (Edge e : u.adjacencies)
        {
            Vertex v = e.target;
            double distanceThroughU = p.distances.get(u) + e.weight;
            if (!p.distances.contains(v) || distanceThroughU < p.distances.get(v)) {
                p.distances.put(v, distance);
                p.backtrack.put(v, u);
            }
            // We didn't prime the queue but we need to make sure we visit everyone
            // at least once.
            if (!visited.contains(v)) {
                vertexQueue.add(v);
                visited.add(v);
            }
        }
    }
    return p;
}

最后,我们可以使用该路径创建路径:

public static List<Vertex> getShortestPathTo(Path p, Vertex target)
{
    List<Vertex> path = new List<Vertex>();
      for (Vertex vertex = target; vertex != null; vertex = p.backtrack.get(vertex))
        path.add(vertex);

    Collections.reverse(path);
    return path;
}
相关问题