【问题标题】:Error in java: Exception in thread "main"java中的错误:线程“main”中的异常
【发布时间】:2015-06-19 22:34:30
【问题描述】:

我正在尝试在 java 中应用 Dijkstra 算法。输入将来自包含 3 列的文本文件,第一个是开始节点,第三个是结束节点,第二个是关系名称,但我现在不需要它,所以我使用第一列和最后一列。 文本文件是:

12	ECrel	15
15	ECrel	18
11	ECrel	12
12	ECrel	14
11	ECrel	14
11	ECrel	18
14	maplink	17
12	maplink	17
14	maplink	10
18	maplink	10
14	maplink	16
15	maplink	19
18	maplink	19
12	maplink	19

任何人都可以看看我的代码并帮助我找出导致此错误的代码中的问题。代码如下:

package shortestPath;
import java.util.Scanner;
import java.io.*;
import java.util.*;

public class Dijkstra {


    public static int count;
    //public static Graph.Edge[] GRAPH = new Graph.Edge[count] ;

    public static void countLines(String file) throws IOException
    {
    LineNumberReader  lnr = new LineNumberReader(new FileReader(new File(file)));
    lnr.skip(Long.MAX_VALUE);
    Dijkstra.count=lnr.getLineNumber() + 1; //Add 1 because line index starts at 0
    // Finally, the LineNumberReader object should be closed to prevent resource leak
    lnr.close();
    //return Dijkstra.count;
    }

    public static Graph.Edge[] readTextFile(String fileName) {

    String line = null;
    Graph.Edge[] Gr=new Graph.Edge[Dijkstra.count];
    try {
        FileReader fileReader = new FileReader("hsa00072.txt");
        // Always wrap FileReader in BufferedReader.
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        // BufferedReader br = new BufferedReader(new InputStreamReader(new
        // FileInputStream(file)));
        int i=0;
        while ((line = bufferedReader.readLine()) != null) {
            String[] tokens = line.split("\\t+");
            String s = tokens[0];
            String e = tokens[2];
            Gr[i] =new Graph.Edge(s, e, 1);
            i=i+1;
        }

        // Always close files.
        bufferedReader.close();
    } catch (FileNotFoundException ex) {
        System.out.println("Unable to open file '" + fileName + "'");
    } catch (IOException ex) {
        System.out.println("Error reading file '" + fileName + "'");
    }
    //return Dijkstra.GRAPH;
    return Gr;
    }


       private static final String START = "10";
       private static final String END = "12";

       public static void main(String[] args) throws IOException {
          countLines("hsa00072.txt"); 
          Graph.Edge[] GRAPH=readTextFile("hsa00072.txt");
          Graph g = new Graph(GRAPH);
          g.dijkstra(START);
          g.printPath(END);


          //g.printAllPaths();
       }
    }

    class Graph {
       private final Map<String, Vertex> graph; // mapping of vertex names to Vertex objects, built from a set of Edges

       /** One edge of the graph (only used by Graph constructor) */
       public static class Edge {
          public final String v1, v2;
          public final int dist;
          public Edge(String v1, String v2, int dist) {
             this.v1 = v1;
             this.v2 = v2;
             this.dist = dist;
          }
       }

       /** One vertex of the graph, complete with mappings to neighbouring vertices */
       public static class Vertex implements Comparable<Vertex> {
          public final String name;
          public int dist = Integer.MAX_VALUE; // MAX_VALUE assumed to be infinity
          public Vertex previous = null;
          public final Map<Vertex, Integer> neighbours = new HashMap<>();

          public Vertex(String name) {
             this.name = name;
          }

          private void printPath() {
             if (this == this.previous) {
                System.out.printf("%s", this.name);
             } else if (this.previous == null) {
                System.out.printf("%s(unreached)", this.name);
             } else {
                this.previous.printPath();
                System.out.printf(" -> %s(%d)", this.name, this.dist);
             }
          }

          public int compareTo(Vertex other) {
             return Integer.compare(dist, other.dist);
          }
       }

       /** Builds a graph from a set of edges */
       public Graph(Edge[] edges) {
          graph = new HashMap<>(edges.length);

          //one pass to find all vertices
          for (Edge e : edges) {
             if (!graph.containsKey(e.v1)) graph.put(e.v1, new Vertex(e.v1));
             if (!graph.containsKey(e.v2)) graph.put(e.v2, new Vertex(e.v2));
          }

          //another pass to set neighbouring vertices
          for (Edge e : edges) {
             graph.get(e.v1).neighbours.put(graph.get(e.v2), e.dist);
             //graph.get(e.v2).neighbours.put(graph.get(e.v1), e.dist); // also do this for an undirected graph
          }
       }

       /** Runs dijkstra using a specified source vertex */ 
       public void dijkstra(String startName) {
          if (!graph.containsKey(startName)) {
             System.err.printf("Graph doesn't contain start vertex \"%s\"\n", startName);
             return;
          }
          final Vertex source = graph.get(startName);
          NavigableSet<Vertex> q = new TreeSet<>();

          // set-up vertices
          for (Vertex v : graph.values()) {
             v.previous = v == source ? source : null;
             v.dist = v == source ? 0 : Integer.MAX_VALUE;
             q.add(v);
          }

          dijkstra(q);
       }

       /** Implementation of dijkstra's algorithm using a binary heap. */
       private void dijkstra(final NavigableSet<Vertex> q) {      
          Vertex u, v;
          while (!q.isEmpty()) {

             u = q.pollFirst(); // vertex with shortest distance (first iteration will return source)
             if (u.dist == Integer.MAX_VALUE) break; // we can ignore u (and any other remaining vertices) since they are unreachable

             //look at distances to each neighbour
             for (Map.Entry<Vertex, Integer> a : u.neighbours.entrySet()) {
                v = a.getKey(); //the neighbour in this iteration

                final int alternateDist = u.dist + a.getValue();
                if (alternateDist < v.dist) { // shorter path to neighbour found
                   q.remove(v);
                   v.dist = alternateDist;
                   v.previous = u;
                   q.add(v);
                } 
             }
          }
       }

       /** Prints a path from the source to the specified vertex */
       public void printPath(String endName) {
          if (!graph.containsKey(endName)) {
             System.err.printf("Graph doesn't contain end vertex \"%s\"\n", endName);
             return;
          }

          graph.get(endName).printPath();
          System.out.println();
       }
       /** Prints the path from the source to every vertex (output order is not guaranteed) */
       public void printAllPaths() {
          for (Vertex v : graph.values()) {
             v.printPath();
             System.out.println();
          }
       }

    }      

错误信息是:

Exception in thread "main" java.lang.NullPointerException
	at shortestPath.Graph.<init>(Dijkstra.java:125)
	at shortestPath.Dijkstra.main(Dijkstra.java:69)

第 69 行是:

Graph g = new Graph(GRAPH);

第 125 行是

if (!graph.containsKey(e.v1)) graph.put(e.v1, new Vertex(e.v1));

【问题讨论】:

  • 你能告诉我们实际的错误信息是什么吗? “线程'main'中的异常”绝对没有向我们传达任何有用的信息。
  • 将异常堆栈跟踪和文件 hsa00072.txt 的内容添加到问题描述中。
  • 这就像你去看医生说... “医生,医生,我感觉不舒服。给我开个处方!” 医生需要知道症状...我们需要查看该堆栈跟踪。 (也就是说……除非您对 IT 等效的糖丸感到满意。您是否尝试过重新安装操作系统?:-))
  • 对于第 125 行的某些迭代,e 可能为空,换句话说,您的边数组中有一个空值。如果Dijkstra.count 计算错误,或者文本文件中的行存在其他问题,则可能会发生这种情况。我最好的建议是使用调试器在第 69 行之前检查 GRAPH 的值,以查看数组中是否有任何空值,然后使用调试器逐步检查 readTextFile 以尝试找出它们的位置来自。
  • 大卫华莱士 .... 非常感谢您的评论非常有用,我弄清楚导致此错误的问题是什么。问题是我将图形的大小设置为计数,但我必须将其设置为 count-1。代码仍然无法正常工作,但此错误已解决...谢谢 :)

标签: java graph-algorithm


【解决方案1】:

感谢您的所有 cmets,但特别感谢 David Wallace,他的评论帮助我了解导致此错误的问题。问题出在这一行

Graph.Edge[] Gr=new Graph.Edge[Dijkstra.count];

我必须将大小设置为 count-1 而不是 count。

谢谢。

【讨论】:

    猜你喜欢
    • 2014-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 2012-12-31
    • 2013-04-30
    相关资源
    最近更新 更多