繁体   English   中英

运行Dijkstra算法实现时的IndexOutOfBoundsException

[英]IndexOutOfBoundsException when running Dijkstra's algorithm implementation

不确定导致此IndexOutOfBoundsException发生的原因。 如果我对所有addFlightPath()参数进行硬编码,代码就可以完美地找到,但是当我尝试使用for循环来填充flightPaths arrayList时,会抛出IndexOutOfBoundsException 我可能错过了一些小东西,但我不确定它可能是什么。

addFlightPath方法中调用flightPaths.add(path)抛出异常

public class DijkstrasController
{
    private FlightDatabase flightDatabase;
    private List<Vertex> nodes;
    private List<Edge> flightPaths;

    public DijkstrasController(FlightDatabase flightDatabase)
    {
        this.flightDatabase = flightDatabase;
        populateDijkstrasGraph(flightDatabase);
    }

    public String[] runDijkstras(String sourceAirport, String destinationAirport)
    {
        //Removed for visibility
    }

    public void populateDijkstrasGraph(FlightDatabase fdb)
    {
        nodes = new ArrayList<Vertex>();
        flightPaths = new ArrayList<Edge>();
        for (int i = 0; i < (fdb.getDatabaseSize()); i++)
        {
            Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
            nodes.add(location);

         //This block of code throws an IndexOutOfBounds error
            AirJourney journey = fdb.getFlightDetails(i);
            String pathId = "Path_" + journey.getOriginAirport() + journey.getDestinationAirport();
            int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
            int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());
            int distance = journey.getNumberOfMilesToTravel();
            addFlightPath(pathId, sourceAirport, destinationAirport, distance);
        }

// Uncommenting this section of code allows the program to function normally
//      addFlightPath("Path_AB", 0, 1, 800);
//      addFlightPath("Path_BC", 1, 2, 900);
//      addFlightPath("Path_CD", 2, 3, 400);
//      addFlightPath("Path_BF", 1, 5, 400);
//      addFlightPath("Path_DE", 3, 4, 300);
//      addFlightPath("Path_EB", 4, 1, 600);
//      addFlightPath("Path_CE", 2, 4, 200);
//      addFlightPath("Path_DC", 3, 2, 700);
//      addFlightPath("Path_EB", 4, 1, 500);
//      addFlightPath("Path_FD", 5, 3, 200);
//      addFlightPath("Path_DE", 3, 4, 400);
//      addFlightPath("Path_CE", 2, 4, 300);

    }

    private void addFlightPath(String pathId, int sourceAirport, int destAirport, int distance)
    {
        Edge path = new Edge(pathId, nodes.get(sourceAirport), nodes.get(destAirport), distance);
        flightPaths.add(path); //IndexOutOfBounds exception is thrown here
    }

}

堆栈跟踪

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
    at java.util.ArrayList.rangeCheck(ArrayList.java:657)
    at java.util.ArrayList.get(ArrayList.java:433)
    at core.dijkstras2.DijkstrasController.addFlightPath(DijkstrasController.java:83)
    at core.dijkstras2.DijkstrasController.populateDijkstrasGraph(DijkstrasController.java:63)
    at core.dijkstras2.DijkstrasController.<init>(DijkstrasController.java:19)
    at core.dijkstras2.DDriver.main(DDriver.java:10)

因此,这个IndexOutOfBounds的原因是由于有问题的for循环阻止了nodes ArrayList被正确填充。

要解决这个问题,我只需更改此代码:

for (int i = 0; i < (fdb.getDatabaseSize()); i++)
        {
            Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
            nodes.add(location);

         //This block of code throws an IndexOutOfBounds error
            AirJourney journey = fdb.getFlightDetails(i);
            String pathId = "Path_" + journey.getOriginAirport() + journey.getDestinationAirport();
            int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
            int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());
            int distance = journey.getNumberOfMilesToTravel();
            addFlightPath(pathId, sourceAirport, destinationAirport, distance);
        }

并且将第二个块移动到单独的for循环中,这允许第一个for循环首先填充arraylist,然后添加飞行路径。

for (int i = 0; i < (fdb.getDatabaseSize()); i++)
        {
            Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
            nodes.add(location);
        }

        for (int i = 0; i < fdb.getDatabaseSize(); i++)
        {
            AirJourney journey = fdb.getFlightDetails(i);
            String pathId = "Path_" + journey.getOriginAirport() + journey.getDestinationAirport();
            int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
            int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());
            int distance = journey.getNumberOfMilesToTravel();
            addFlightPath(pathId, sourceAirport, destinationAirport, distance);
        }

正如评论中所提到的,您的例外似乎源于以下行:

Edge path = new Edge(pathId, nodes.get(sourceAirport), nodes.get(destAirport), distance);

让我们来看看你的populateDijkstrasGraph()函数(违规部分):

    for (int i = 0; i < (fdb.getDatabaseSize()); i++)
    {
        Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
        nodes.add(location);

在这里添加nodeNumberToNodeLetter(i)给出的位置。

        int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
        int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());

在这里,您将获得前两个机场节点的整数值。 但是,我们只添加了一个节点! (上面的nodes.add(location) )。

因此,如果sourceAirport == 0destinationAirport == 1nodes当前只包含一个Vertex ,则nodes.get(sourceAirport)将起作用,而nodes.get(destinationAirport)将按预期抛出IndexOutOfBoundsException

解决此问题的一种方法是在尝试填充节点之间的边之前填充节点列表。

编辑:如果您还没有,则应在IDE中启用行号。 它使调试更容易。 此外,您应该熟悉调试和断点 - 这样可以让您很快找到上述错误。

一些猜测工作,但我认为你的代码的工作版本看起来像这样:

public void populateDijkstrasGraph(FlightDatabase fdb)
{
    nodes = new ArrayList<Vertex>();
    flightPaths = new ArrayList<Edge>();
    for (int i = 0; i < (fdb.getDatabaseSize()); i++)
    {
        Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
        nodes.add(location);

     //This block of code throws an IndexOutOfBounds error
     //   AirJourney journey = fdb.getFlightDetails(i);
     //   String pathId = "Path_" + journey.getOriginAirport() + journey.getDestinationAirport();
     //   int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
     //   int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());
     //   int distance = journey.getNumberOfMilesToTravel();
     //   addFlightPath(pathId, sourceAirport, destinationAirport, distance);
    }

// Uncommenting this section of code allows the program to function normally
   addFlightPath("Path_AB", 0, 1, 800);
   addFlightPath("Path_BC", 1, 2, 900);
   addFlightPath("Path_CD", 2, 3, 400);
// etc.

这样可以正常工作,因为您有一个完全填充的nodes List。 如果将addFlightPath移动到for -loop中,则nodes在循环的第一次迭代中只包含一个元素。 因此,对nodes.get(1)的调用将因IndexOutOfBounds异常而失败。

您可能需要循环两次:

for (int i = 0; i < (fdb.getDatabaseSize()); i++)
{
    Vertex location = new Vertex("Node_" + i, nodeNumberToNodeLetter(i));
    nodes.add(location);
}

for (int i = 0; i < (fdb.getDatabaseSize()); i++)
{
    AirJourney journey = fdb.getFlightDetails(i);
    String pathId = "Path_" + journey.getOriginAirport() + journey.getDestinationAirport();
    int sourceAirport = nodeLetterToNodeNumber(journey.getOriginAirport());
    int destinationAirport = nodeLetterToNodeNumber(journey.getDestinationAirport());
    int distance = journey.getNumberOfMilesToTravel();
    addFlightPath(pathId, sourceAirport, destinationAirport, distance);
}

当您执行循环时,始终从您使用的列表的0到大小-1开始。 如果你有一个5位的列表,循环从0到4.也许它是你的问题?

试着把:

for (int i = 0; i < (fdb.getDatabaseSize()-1); i++)
{}

暂无
暂无

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

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