Search code examples
javaioadjacency-matrix

how to create an adjacency matrix, using an input text file, to represent a directed weighted graph [java]?


I'm having a hard time figuring out how to create an adjacency matrix from an input file. The input file is supposed to represent a directed, weighted graph of nodes.

The purpose is to create a program that can do a iterative depth first search, but I'm really stuck on the data input part of the assignment.

The input text file would supposedly look like the following:

each node is represented by two lines of text. For example the on the very top line, the first 'S' is the name of the node, the second 'S' indicates that it's a start node, the third 'n' indicates that it's a regular node, not a goal node, which would be indicated by a 'g'.

On the second line are the two nodes connected to 'S' the first being 'B' with a weighted distance of 1, and the second being 'E' with a weighted distance of 2.

The third line is supposed to be blank, and the pattern is repeated.

S S n                     
B 1 E 2            


B N n

C 2 F 3


C N n

D 2 GA 4

D N n

GA 1

E N n

B 1 F 3 H 6

F N n

I 3 GA
 3 C 1

GA N g

H N n

I 2 GB 2 F 1

I N n

GA 2 GB 2

GB N g

I'm really stuck on this. I have been using buffered reader to scan in the file but I've been wondering if using Scanner would be easier.

I'm currently attempting to create Node objects with the attributes of having a name, and maybe a link to other adjacent Node objects using a linked list of some kind. I've also considered using an array of node objects but I'm really unsure how to represent which nodes connect to which other nodes and how to build that into an adjacency matrix using a two dimensional array.

Any suggestions would be greatly appreciated, I'm a newbie so I apologize if my question is not of academic importance to others

Edit: my code is something like this: public void actionPerformed(ActionEvent e) {

    if(e.getSource() == openButton)
    {
        returnVal = fileChooser.showOpenDialog(null);

        if(returnVal == JFileChooser.APPROVE_OPTION)
        {
            selected_file = fileChooser.getSelectedFile();

            String file_name = fileChooser.getSelectedFile().getName();
            file_name = file_name.substring(0, file_name.indexOf('.'));

            try
            {
                BufferedWriter buff_writer = null;
                File newFile = new File("."+file_name+"_sorted.txt");           

                boolean verify_creation = newFile.createNewFile();
                //if (verify_creation)
                //  System.out.println("file created successfully");
                //else
                //  System.out.println("file already present in specified location");

                file_reader1 = new BufferedReader(new FileReader(selected_file));
                file_reader2 = new BufferedReader(new FileReader(selected_file));

                FileWriter file_writer = new FileWriter(newFile.getAbsoluteFile());
                buff_writer = new BufferedWriter(file_writer);

                //find the number of nodes in the file
                while( (currentLine = file_reader1.readLine()) != null)
                {
                    k++;
                    System.out.println("value of k: " + k);
                }


                nodeArray = new Node[k];

                while( (currentLine = file_reader2.readLine()) != null) 
                {   
                    //System.out.print(currentLine);

                    String[] var = currentLine.split(" ");


                    nodeArray[x] = new Node(var[0], var[1], var[2]);
                    nodeArray[x].setLink1(new Node(var[3], null, null));



                }

            buff_writer.close();
            file_writer.close();

            }   
            catch (Exception e1)
            {
                e1.printStackTrace();
            }       
        }
    }

Edit #2

my node object looks something like this:

public Node(String n, String t1, String t2)
{
    name = n;
    type1 = t1;
    type2 = t2;

    link1 = null;
    link2 = null;
    link3 = null;
    link4 = null;
    link5 = null;
    link6 = null;

Solution

  • Thing is: you do not want to use a two-dimensional array here. You want to step back and design/model a class/data structure that fits the "actual problem" you are working.

    In other words: your problem is about representing a graph of nodes and edges. So, some tips to get you going ..

    Lets start with:

    enum NodeType { START, GOAL, NORMAL ; }
    
    public class Node {
      private final String name;
    
      public Node(String name) {
        this.name = name;
    

    The above gives you a reasonable way to distinguish the different types of nodes. And then we start with the representation of a node. Obviously, its name is fixed - you dont want to change the name of a node after it was created. Then you have setters like

    public void setType(NodeType type) ...
    

    And more fields,

    private final Map<Node, Integer> neighbors = new HashMap<>();
    

    and a method to add a new neighbor:

    public void addNeighborNode(Node node, int weight) {
       neighbors.put(node, weight);
    

    [ for the record: theoretically, you could create a class that takes all infos via a constructor, avoiding the need of having setter methods. that has certain advantages, but makes things more complicated; and I guess ... what I am showing you here is complicated enough already ;-) ]

    The whole idea here - you separate the PARSING from the way how you represent/build your objects. Of course, at some point you have to read that strings, to then build node objects from them.

    But you better start with a Node class like above, because then you can build a graph ... without the need to parse a text file:

    Node n1 = new Node("n1");
    n1.setType(NodeType.START);
    
    Node n2 = new Node("n2");
    n2.setType(NodeType.GOAL);
    
    n1.setNeighborNode(n2, 5);
    

    In other words: first you build a nice "class model" for a graph. And you can write test code like above. And when all of that works; then you write the code that reads that input file and translates that into the method calls you need to build your graph!

    Long story short: of course, parsing that text file is important, but you should not focus on that. Instead: think a lot about the class model of your data first. That is were you can learn the most, and have the most fun in experimenting. Pulling in strings and turning them into objects, that is just "work". Have some fun first!