Dijkstra的算法邻接表Java

时间:2017-05-14 21:32:01

标签: java algorithm dijkstra

如果我犯了任何错误,请原谅我,这是我的第一篇文章之一,所以请耐心等待。我试图用邻接列表实现Dijkstra算法,但由于某种原因我得出了不良结果,从下面的代码中,你会看到SFO-> NYC有一个明显的路径,有一个权重232,但是当你运行代码时,无穷大就是输出。

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 Dijkstra
{
    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 SFO = new Vertex("SFO");
        Vertex NYC = new Vertex("NYC");
        Vertex SEA = new Vertex("SEA");
        Vertex GDL = new Vertex("GDL");
        Vertex CUU = new Vertex("CUU");
        Vertex MEX = new Vertex("MEX");
        Vertex PAR = new Vertex("PAR");
        Vertex MRS = new Vertex("MRS");
        Vertex LYS = new Vertex("LYS");
        Vertex PVG = new Vertex("PVG");
        Vertex PEK = new Vertex("PEK");
        Vertex CAN = new Vertex("CAN");
        Vertex DEL = new Vertex("DEL");
        Vertex BOM = new Vertex("BOM");
        Vertex MAA = new Vertex("MAA");
        Vertex MEL = new Vertex("MEL");
        Vertex SYD = new Vertex("SYD");
        Vertex PER = new Vertex("PER");
        Vertex NBO = new Vertex("NBO");
        Vertex MBA = new Vertex("MBA");
        Vertex KIS = new Vertex("KIS");
        Vertex CGK = new Vertex("CGK");
        Vertex SUB = new Vertex("SUB");
        Vertex BDO = new Vertex("BDO");
        Vertex CGH = new Vertex("CGH");
        Vertex GIG = new Vertex("GIG");
        Vertex SSA = new Vertex("SSA");
        Vertex MOW = new Vertex("MOW");
        Vertex LED = new Vertex("LED");
        Vertex KZN = new Vertex("KZN");

        // set the edges and weight
        SFO.adjacencies = new Edge[]{ new Edge(NYC, 232) };
        SFO.adjacencies = new Edge[]{ new Edge(MEX, 226) };

        NYC.adjacencies = new Edge[]{ new Edge(MEL, 942) };
        NYC.adjacencies = new Edge[]{ new Edge(SYD, 930) };

        SEA.adjacencies = new Edge[]{ new Edge(PEK, 667) };
        SEA.adjacencies = new Edge[]{ new Edge(KIS, 4127) };


        GDL.adjacencies = new Edge[]{ new Edge(KIS, 2294) };
        GDL.adjacencies = new Edge[]{ new Edge(SUB, 1300) };

        CUU.adjacencies = new Edge[]{ new Edge(SEA, 379) };
        CUU.adjacencies = new Edge[]{ new Edge(GDL, 34) };

        MEX.adjacencies = new Edge[]{ new Edge(PAR, 609) };
        MEX.adjacencies = new Edge[]{ new Edge(KZN, 1302) };

        PAR.adjacencies = new Edge[]{ new Edge(LYS, 65) };
        PAR.adjacencies = new Edge[]{ new Edge(MBA, 462) };

        MRS.adjacencies = new Edge[]{ new Edge(CUU, 1948) };
        MRS.adjacencies = new Edge[]{ new Edge(PVG, 537) };

        LYS.adjacencies = new Edge[]{ new Edge(SUB, 1073) };

        PVG.adjacencies = new Edge[]{ new Edge(SEA, 373) };

        PEK.adjacencies = new Edge[]{ new Edge(CAN, 254) };
        PEK.adjacencies = new Edge[]{ new Edge(MAA, 345) };

        CAN.adjacencies = new Edge[]{ new Edge(BOM, 363) };

        DEL.adjacencies = new Edge[]{ new Edge(SEA, 667) };
        DEL.adjacencies = new Edge[]{ new Edge(PEK, 263) };

        BOM.adjacencies = new Edge[]{ new Edge(KZN, 539) };

        MAA.adjacencies = new Edge[]{ new Edge(CAN, 201) };
        MAA.adjacencies = new Edge[]{ new Edge(BOM, 29) };

        MEL.adjacencies = new Edge[]{ new Edge(PER, 118) };
        MEL.adjacencies = new Edge[]{ new Edge(LED, 810) };

        SYD.adjacencies = new Edge[]{ new Edge(MEX, 1004) };

        PER.adjacencies = new Edge[]{ new Edge(PAR, 729) };
        PER.adjacencies = new Edge[]{ new Edge(NBO, 783) };

        NBO.adjacencies = new Edge[]{ new Edge(CGH, 1140) };
        NBO.adjacencies = new Edge[]{ new Edge(GIG, 899) };

        MBA.adjacencies = new Edge[]{ new Edge(CGK, 611) };
        MBA.adjacencies = new Edge[]{ new Edge(MOW, 786) };

        KIS.adjacencies = new Edge[]{ new Edge(PEK, 809) };
        KIS.adjacencies = new Edge[]{ new Edge(DEL, 972) };

        CGK.adjacencies = new Edge[]{ new Edge(MRS, 651) };
        CGK.adjacencies = new Edge[]{ new Edge(BDO, 85) };

        SUB.adjacencies = new Edge[]{ new Edge(SEA, 1045) };
        SUB.adjacencies = new Edge[]{ new Edge(PVG, 261) };

        BDO.adjacencies = new Edge[]{ new Edge(NBO, 984) };
        BDO.adjacencies = new Edge[]{ new Edge(SUB, 65) };

        CGH.adjacencies = new Edge[]{ new Edge(LYS, 727) };
        CGH.adjacencies = new Edge[]{ new Edge(CGK, 1794) };

        GIG.adjacencies = new Edge[]{ new Edge(CUU, 595) };
        GIG.adjacencies = new Edge[]{ new Edge(SSA, 90) };

        SSA.adjacencies = new Edge[]{ new Edge(CGK, 1978) };
        SSA.adjacencies = new Edge[]{ new Edge(BDO, 5634) };

        MOW.adjacencies = new Edge[]{ new Edge(MAA, 381) };
        MOW.adjacencies = new Edge[]{ new Edge(GIG, 759) };
        MOW.adjacencies = new Edge[]{ new Edge(KZN, 52) };

        LED.adjacencies = new Edge[]{ new Edge(PER, 825) };
        LED.adjacencies = new Edge[]{ new Edge(MOW, 53) };

        KZN.adjacencies = new Edge[]{ new Edge(MAA, 551) };
        KZN.adjacencies = new Edge[]{ new Edge(LED, 96) };

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

1 个答案:

答案 0 :(得分:0)

你有几个问题:

  • 首先,您打印的距离为MAA而不是NYC。这是一个简单的修复:

    System.out.println("Distance to " + NYC + ": " + NYC.minDistance);
    
  • 其次,每次添加内容时都会覆盖邻接列表:

    SFO.adjacencies = new Edge[]{ new Edge(NYC, 232) };
    SFO.adjacencies = new Edge[]{ new Edge(MEX, 226) }; //This is a whole new list
    //SFO.adjacencies only contains edge MEX now, as the old list was overwritten
    

    更改为:

    SFO.adjacencies = new Edge[]{ new Edge(NYC, 232), new Edge(MEX, 226) };
    //Now list contains both edges as desired
    

这将解决您当前的问题,但我也注意到了几个算法问题:

  • 您的vertexQueue应该以所有顶点开头,您只需添加source。因此,目前,您只能找到与您的来源相邻的内容。

  • 为什么要从内部v的{​​{1}}中移除vertexQueue,只是为了在最后重新添加它?这没什么。

查看this pseudocode并确保您的算法与之一致。