首页 > 解决方案 > 尝试实现 dijkstra 的算法(在我无法完全修复的线程中遇到异常)

问题描述

我必须实施 dijkstra 的算法以找到与道路相连的各个城市之间的最短路径。每条道路都有固定的成本,每个城市都有固定的停留成本。任务只是找到第一个和第二个节点之间的最短路径,最少有 3 个节点,但我写了我的找到源和所有节点之间的最短路径。

通过首先给出城市(节点)的数量,然后是道路(链接)的数量来输入数据。然后每个城市(节点)都以“#city cost”格式读取它的成本。然后将链接读入为“#first_city #second_city cost”。我将它们存储在一个二维数组中,其中第一个维度是城市,第二个维度是从每个城市前往其他城市的成本。我最初在没有链接的城市之间有成本初始化为空,但我开始得到我目前正在处理的异常。

以下是我输入数据的方式:

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

我当前的 dijkstra 函数定义如下:

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

我不断收到以下异常:

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

我当前的测试输入是:

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

从第一个节点到第二个节点的成本的正确输出应该是 388 美元。

我测试了一些东西,主要是为了隔离异常,它似乎在 if 语句的这一部分:

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

如果您想对其进行测试,我可以发布 github 链接,但我更愿意将内容保密以阻止任何复制。

标签: javanullpointerexceptioncomputer-sciencedijkstra

解决方案


正如我在评论中已经说过的那样,我不得不猜测,但我认为拆箱的尝试会roads[u][x]引发 NPE。

为什么?因为你像这样初始化它:

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

正如您所看到的,roads[0][j]可能永远不会被初始化,所以只要u是 0,您就会得到 NPE,因为其中的所有元素roads[0]仍然为空。

您有一个设置roads[a][b]等的循环(注释为“//读取每条道路上的燃气成本”),但因为ab设置为readInt() - 1;那些可能永远不会为 0(至少由于缺少代码我无法判断) .

TLDR:Integer在使用原始包装器(或它们的数组)时,以及在需要原始包装器(等)并且自动拆箱尝试转换为原始包装器Boolean的情况下,您可能很难发现和理解 NullPointerExceptions 。intbooleannull


推荐阅读