简体   繁体   English

运行Dijkstra算法实现时的IndexOutOfBoundsException

[英]IndexOutOfBoundsException when running Dijkstra's algorithm implementation

Not particularly sure what's causing this IndexOutOfBoundsException to occur. 不确定导致此IndexOutOfBoundsException发生的原因。 The code works perfectly find if I hard code all of the addFlightPath() parameters, but as soon as I attempt to use a for loop to populate the flightPaths arrayList an IndexOutOfBoundsException is thrown. 如果我对所有addFlightPath()参数进行硬编码,代码就可以完美地找到,但是当我尝试使用for循环来填充flightPaths arrayList时,会抛出IndexOutOfBoundsException I'm probably missing something small but I'm not sure what it could be. 我可能错过了一些小东西,但我不确定它可能是什么。

The exception is thrown on the call to flightPaths.add(path) within the addFlightPath method 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
    }

}

Stack Trace 堆栈跟踪

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)

So, the reason for this IndexOutOfBounds was being caused by the fact that the for loop in question prevented the nodes ArrayList from being populated properly. 因此,这个IndexOutOfBounds的原因是由于有问题的for循环阻止了nodes ArrayList被正确填充。

To fix this, I simply changed this code: 要解决这个问题,我只需更改此代码:

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);
        }

And moved the second block into a separate for loop, this allows the first for loop to populate the arraylist first, before the flight paths are added. 并且将第二个块移动到单独的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);
        }

As mentioned in the comments, your exception seems to be stemming from the following line: 正如评论中所提到的,您的例外似乎源于以下行:

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

Let's go over your populateDijkstrasGraph() function (offending portion): 让我们来看看你的populateDijkstrasGraph()函数(违规部分):

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

Here you add the location given by nodeNumberToNodeLetter(i) . 在这里添加nodeNumberToNodeLetter(i)给出的位置。

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

Here, you are getting the integer values for the first two airport nodes. 在这里,您将获得前两个机场节点的整数值。 However, we've only added a single node! 但是,我们只添加了一个节点! ( nodes.add(location) above). (上面的nodes.add(location) )。

Thus, if sourceAirport == 0 and destinationAirport == 1 , with nodes currently containing only a single Vertex , nodes.get(sourceAirport) will work, whereas nodes.get(destinationAirport) will throw an IndexOutOfBoundsException , as expected. 因此,如果sourceAirport == 0destinationAirport == 1nodes当前只包含一个Vertex ,则nodes.get(sourceAirport)将起作用,而nodes.get(destinationAirport)将按预期抛出IndexOutOfBoundsException

One way to fix this would be to populate the list of nodes before attempting to populate the edges between them. 解决此问题的一种方法是在尝试填充节点之间的边之前填充节点列表。

Edit: If you haven't already, you should enable line numbers in your IDE. 编辑:如果您还没有,则应在IDE中启用行号。 It makes debugging much easier. 它使调试更容易。 In addition, you should familiarize yourself with debugging and breakpoints - this would've allowed you to find the above error quite quickly. 此外,您应该熟悉调试和断点 - 这样可以让您很快找到上述错误。

A bit of guess work, but I assume that your working version of the code looks something like this: 一些猜测工作,但我认为你的代码的工作版本看起来像这样:

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.

This will work fine since you have a fully populated nodes List. 这样可以正常工作,因为您有一个完全填充的nodes List。 If you move addFlightPath into the for -loop though, nodes will only contain one element in the first iteration through the loop. 如果将addFlightPath移动到for -loop中,则nodes在循环的第一次迭代中只包含一个元素。 Hence the call to nodes.get(1) will fail with the IndexOutOfBounds exception. 因此,对nodes.get(1)的调用将因IndexOutOfBounds异常而失败。

You will probably need to loop twice: 您可能需要循环两次:

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);
}

When you do a loop always start from 0 to size -1 of the list you use. 当您执行循环时,始终从您使用的列表的0到大小-1开始。 If you have a list of 5 position, the loop goes from 0 to 4. Maybe its your problem? 如果你有一个5位的列表,循环从0到4.也许它是你的问题?

Try to put: 试着把:

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

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

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