简体   繁体   中英

Representing a graph with an unknown number of nodes?

For the last few days I cannot think about how to represent a given graph in a text file into an adjacency matrix without knowing the number of vertices in the graph beforehand.

The input file has vertices defined as Strings and a pair of consecutive lines representing an edge between both vertices. For example:

VertexA
VertexB
VertexC
VertexD

There is an edge from VertexA -> VertexB and VertexC -> VertexD in the above example. Directed, weights are arbitrarily 1.

I would like to implement this in it's own class which doesn't parse the file directly and instead has only a method which adds a directed between a given source and destination vertex. For example:

// adds a directed edge from vertex1 -> vertex2
addEdgeBetweenVertices(String vertex1, String vertex2);

In this method so far I have made a HashMap and if either vertex is not in the map, add it with it's own unique index. (The key being the name of the vertex and the value being its index.)

How can I construct this adjacency matrix using such a method, while maintaining this edge information, but without knowing the number of vertices ( |V| ) prior?

I was thinking an ArrayList of ArrayLists but I can't wrap my head around this.

You can use ArrayList of ArrayList and your idea is perfect that you can map the String s with unique Integer ids and then directly add the corresponding vertex to the list.

The problem with Adjacency Matrix is that you need to know the maximum limit of the vertexes. Adjacency Matrix is not memory efficient and also not feasible for dynamic operations. So here Adjacency List comes into the picture. I have written a small code to demonstrate the creation of Adjacency List and also how to add new Vertex or and Edge .

import java.util.ArrayList;
import java.util.HashMap;

public class AdjacencyListDemo {

    static int availableId=0;                            //Represents the available id for mapping
    static HashMap<String,Integer> mapping;              //To store the String-Integer mapping for Vertexes
    static ArrayList<ArrayList<Integer>> adjacencyList;

    public static void main(String args[])
    {
        adjacencyList = new ArrayList<ArrayList<Integer>>();

        mapping  = new HashMap<String,Integer>();

        String sampleVertexes[] = {"Vertex1","Vertex2","Vertex3","Vertex4"};

        for(String vertex : sampleVertexes)
            addNewVertex(vertex);

        addEdgeBetween("Vertex1","Vertex2");
        addEdgeBetween("Vertex3","Vertex4");

        System.out.println("Old List: ");
        printList();

        //Add New Vertex if required
        addNewVertex("Vertex5");

        addEdgeBetween("Vertex5","Vertex1");
        addEdgeBetween("Vertex2","Vertex1");
        addEdgeBetween("Vertex3","Vertex2");
        addEdgeBetween("Vertex5","Vertex2");

        System.out.println("\n\nNew List: ");
        printList();

    }

    private static void printList()
    {
        for(String vertex : mapping.keySet()) {
            int index = mapping.get(vertex);
            System.out.println(vertex+" ID: "+index+" List: "+adjacencyList.get(index));
        }
    }
    private static void addEdgeBetween(String vertex1, String vertex2) {
        //get both indexes
        int index1 = mapping.get(vertex1);
        int index2 = mapping.get(vertex2);

        //add index2 into the arraylist of index1 
        adjacencyList.get(index1).add(index2);
    }

    private static void addNewVertex(String vertex) {

        if(!mapping.containsKey(vertex))
        {  
            //assign available ID
            mapping.put(vertex,availableId);
            availableId++;                                   //make increment in available id
            adjacencyList.add(new ArrayList<Integer>());     //Add an Empty ArrayList
        }
    }
}

Output :

Old List: 
Vertex2 ID: 1 List: []
Vertex3 ID: 2 List: [3]
Vertex1 ID: 0 List: [1]
Vertex4 ID: 3 List: []


New List: 
Vertex2 ID: 1 List: [0]
Vertex3 ID: 2 List: [3, 1]
Vertex1 ID: 0 List: [1]
Vertex4 ID: 3 List: []
Vertex5 ID: 4 List: [0, 1]

I would say that both the Map and the ArrayList of ArrayList s can be part or a solution. Use the Map<String,int> to obtain the unique id for each vertex string, as you already described. Then something like this might work (sorry just more or less Java)

HashMap<String,Integer> map;
ArrayList< ArrayList<Boolean> > adjacency;

addEdgeBetweenVertices(String vertex1, String vertex2) {
  Integer idx1 = (map.containsValue(vertex1)) ? map.get(vertex1) : map.put(vertex1,getNextIndex());
  Integer idx2 = (map.containsValue(vertex1)) ? map.get(vertex2) : map.put(vertex2,getNextIndex());

  adjacency[idx1].set(idx2,true);
}

If you don't need to use that adjacency matrix after most of calls to addEdgeBetweenVertices , then you can add data about your edges to some array. And just before you want to use it call Build (or Rebuild ) member function of your class (you will need to add this one). Which will actually build your adjacency matrix.

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