简体   繁体   中英

Trying to Implement dijkstra's algorithm (Running into Exception in thread that I can't quite fix)

I have to implement dijkstra's algorithm for an assignment to find the shortest path between various cities that are interconnected with roads. Each road has a fixed cost and each city has a fixed cost of stay. The assignment is just to find the shortest path between the first and second node with a minimum number of 3 nodes but I wrote mine to find the shortest path between a source and all nodes.

The data is input by first giving the number of cities (nodes) and then the number of roads (links). Then Each city(node) has it's cost read in in the format "#citie cost". Then the links are read in as "#first_city #second_city cost". I store them in a 2D array where the first dimension is the cities and the second is the cost of traveling to other cities from each one. I originally had costs between cities that had no link's initialized as null but I started getting the Exception I'm currently dealing with.

Below is how I am inputting the data:

private Integer num_cities;
private Integer num_roads;

public static void main(String[] args) {

        test p = new test();
        

        p.num_cities = readInt();
        p.num_roads = readInt();

        Integer [][] roads = new Integer[p.num_cities][p.num_roads];

        Integer [] hotel_cost = new Integer[p.num_cities];

        //Reading in Hotel Costs at Each City
        hotel_cost[0] = 0;
        hotel_cost[1] = 0;
        for (Integer i = 2; i < p.num_cities; i++) {
            Integer hotel = readInt() - 1;
            hotel_cost[hotel] = readInt();
        }

        //filling with no connections
        for (Integer i = 1; i < p.num_cities; i++) {
            for (Integer j = 0; j < p.num_roads; j++) {
                roads[i][j] = 0;
            }
        }

        //Reading in Gas Costs on Each Road
        for (Integer i = 0; i < p.num_roads; i++) {
            Integer a = readInt() - 1;
            Integer b = readInt() - 1;
            Integer cost = readInt();
            roads[a][b] = cost;
            roads[b][a] = cost;
        }

        p.dijkstra(roads, hotel_cost, 0);
    
    
    }
}

My current dijkstra function is defined as below:

    public Integer minDistance(Integer cost[], Boolean b[]) {
        Integer min = Integer.MAX_VALUE, index = -1;
        for (Integer x = 0; x < num_cities; x++) {
            if (b[x] == false && cost[x] <= min) {
                min = cost[x];
                index = x;
            }
        }
        return index;
    }


    public void dijkstra(Integer roads[][], Integer hotel_cost[], Integer src) {

        Integer cost[] = new Integer[num_cities];

        Boolean b[] = new Boolean[num_cities];

        for(Integer i = 0; i < num_cities; i++) {
            cost[i] = Integer.MAX_VALUE;
            b[i] = false;
        }

        cost[src] = 0;
        for (Integer count = 0; count < num_cities; count++) {
            Integer u = minDistance(cost, b);
            b[u] = true;
            for (Integer x = 0; x < num_roads; x++) {
                if (!b[x] && (roads[u][x] + hotel_cost[u]) != 0 && cost[u] != Integer.MAX_VALUE && cost[u] + roads[u][x] + hotel_cost[u] < cost[x] ) {
                    cost[x] = cost[u] + roads[u][x] + hotel_cost[x];
                }
            }
        }
        printCostChart(cost, num_cities);
    }

I keep getting the following exception:

Exception in thread "main" java.lang.NullPointerException
        at cmsc401.dijkstra(cmsc401.java:72)
        at cmsc401.main(cmsc401.java:116)

My current test input is:

5 
7 
3 78 
4 87 
5 98 
1 4 98 
5 4 45 
1 5 140 
4 3 87 
2 5 150 
3 5 109 
3 2 73

The correct output for the cost to travel from the first node to the second node should be $388.

I've tested a few things mainly trying to isolate the exception and it seemed to be in this part of the if statement:

!b[x] && (roads[u][x] + hotel_cost[u]) != 0

If you'd like to test it I can post the github link but I prefer to keep things private to stop any copying.

As I've already stated in my comment I'd have to guess but I assume the attempt to unbox roads[u][x] throws the NPE.

Why? Because you intialize it like this:

for (Integer i = 1; i < p.num_cities; i++) {
   for (Integer j = 0; j < p.num_roads; j++) {
      roads[i][j] = 0;
   }
}

As you can see roads[0][j] might never be initialized so whenever u is 0 you get the NPE because all elements in roads[0] are still null.

You have a loop that sets roads[a][b] etc. (commented with "//Reading in Gas Costs on Each Road") but since a and b are set to readInt() - 1; those might never be 0 as well (at least I can't tell due to the missing code).

TLDR: you might get hard to spot and understand NullPointerExceptions when using primitive wrappers (or arrays of those) like Integer and Boolean in situations where a primitive ( int , boolean etc.) is needed and auto-unboxing tries to convert null to a primitive.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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