Search code examples
javagraphnodesfilereadervertices

Reading number of node from text file in graph


I want to read how many nodes in a text file where it only consists of edges. I do not want to add in the top of my text file to read the number of vertices. Here's what contains in the text file.

11 3
2 3
0 3
1 4
5 4
5 7
6 7
7 8
8 9
9 10
0 5

The problem is I cannot get the number of nodes from reading a file. I was thinking if finding the maximum value of nodes and add 1 if it starts with 0. But still I couldn't get it so I tried by reading the nextInt and compare with another nextInt. Here's what I have mean and what is done so far.

public static int readNode(String mazeFile) {
    int numNode = 0;
    File mf = new File(mazeFile);
    try {
        Scanner scan = new Scanner(mf);
        int arc = readLineCount(mf);
        for (int i = 0; i < arc; i++) {
            while (scan.hasNext()) {
                int n1 = scan.nextInt();
                int n2 = scan.nextInt();
                if (n1 > n2) {
                    n2 = n1;
                    numNode = n2;
                } else if (n1 < n2) {
                    n1 = n2;
                    numNode = n1;
                }
            }
        }
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return numNode;
}

Do I need to change something?


Solution

  • With this method you're still counting on the user to give the graph with consecutive integer node numbers. What if someone picks a node number of 1111111111 when there are only 42 nodes in the graph? To fix this, think of node numbers as symbols.

    import java.io.File;
    import java.io.FileNotFoundException;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Scanner;
    import java.util.Set;
    
    class Graph {
      final Set<Integer> nodes = new HashSet<>();
      final Map<Integer, Set<Integer>> edges = new HashMap<>();
    
      static class Reader {
        String fileName;
        Graph graph;
    
        Reader(String fileName) {
          this.fileName = fileName;
        }
    
        Graph read() {
          try {
            return scanGraph();
          } catch (FileNotFoundException ignore) {
            return new Graph();
          }
        }
    
        Graph scanGraph() throws FileNotFoundException {
          graph = new Graph();
          Scanner scanner = new Scanner(new File(fileName));
          while (scanner.hasNextInt()) {
            int n1 = scanner.nextInt();
            int n2 = scanner.nextInt();
            graph.nodes.add(n1);
            graph.nodes.add(n2);
            addDirectedEdge(n1, n2);
          }
          return graph;
        }
    
        void addDirectedEdge(Integer n1, Integer n2) {
          if (graph.edges.containsKey(n1)) {
            graph.edges.get(n1).add(n2);
          } else {
            Set<Integer> to = new HashSet<>();
            to.add(n2);
            graph.edges.put(n1, to);
          }
        }    
      }
    
      interface Visitor {
        void visit(int node);
      }    
    
      void visitDepthFirst(int start, Visitor visitor) {
        visitDepthFirst(start, visitor, new HashSet<>());
      }
    
      void visitDepthFirst(int node, Visitor visitor, Set<Integer> visited) {
        visitor.visit(node);
        visited.add(node);
        Set<Integer> successors = edges.get(node);
        if (successors == null) {
          return;
        }
        for (int successor : successors) {
          if (!visited.contains(successor)) {
            visitDepthFirst(successor, visitor, visited);
          }
        }
      }
    
      public static void main(String [] args) {
        Graph graph = new Graph.Reader(args[0]).read();
        System.out.println("The graph has " + graph.nodes.size() + " nodes:");
        System.out.println(graph.nodes);
        System.out.println("Adjacency list:");
        System.out.println(graph.edges);
        System.out.println("A preorder depth first visit starting from 0:");
        graph.visitDepthFirst(0, new Visitor() {
          @Override
          public void visit(int node) {
            System.out.println("Visiting " + node);
          }
        });
      }
    }
    

    I've fixed some other questionable practice in your code as well. But I haven't used Java 8 functional features, which would make this less verbose.

    The output:

    The graph has 12 nodes:
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    Adjacency list:
    {0=[3, 5], 1=[4], 2=[3], 5=[4, 7], 6=[7], 7=[8], 8=[9], 9=[10], 11=[3]}
    A preorder depth first visit starting from 0:
    Visiting 0
    Visiting 3
    Visiting 5
    Visiting 4
    Visiting 7
    Visiting 8
    Visiting 9
    Visiting 10
    

    NB for brevity I've omitted the niceties of production Java like public/private and getters/setters.