表示具有未知数量节点的图形?

时间:2017-06-01 08:22:16

标签: java algorithm data-structures graph

在过去的几天里,我无法考虑如何在不知道图中顶点数量的情况下将文本文件中的给定图表表示为邻接矩阵。

输入文件的顶点定义为字符串,一对连续的线表示两个顶点之间的边。例如:

VertexA
VertexB
VertexC
VertexD

VertexA有一个优势 - > VertexB和VertexC - >上例中的VertexD。定向,权重是任意的。

我想在它自己的类中实现它,它没有直接解析文件而只有一个方法,它在给定的源和目标之间添加一个指向顶点。例如:

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

到目前为止,在这个方法中,我创建了一个HashMap,如果任何一个顶点不在地图中,请添加它自己的唯一索引。 (键是顶点的名称,值是索引。)

如何使用这样的方法构造这个邻接矩阵,同时保持这个边缘信息,但不知道先前的顶点数(| V |)?

我在想ArrayLists的ArrayList,但我无法解决这个问题。

3 个答案:

答案 0 :(得分:2)

您可以使用ArrayList of ArrayList,您的想法非常完美,您可以使用唯一的String ID映射Integer,然后直接将相应的顶点添加到列表中。

Adjacency Matrix的问题是您需要知道顶点的最大限制。 Adjacency Matrix不是memory efficient,也不适用于动态操作。所以这里Adjacency List就出现了。我编写了一个小代码来演示邻接列表的创建,以及如何添加新的VertexEdge

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

输出:

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]

答案 1 :(得分:1)

我会说,Map的{​​{1}}和ArrayList都可以是部分或解决方案。如您所述,使用ArrayList获取每个Map<String,int>字符串的唯一id。那么像这样的东西可能会起作用(抱歉只是或多或少Java)

vertex

答案 2 :(得分:1)

如果在大多数addEdgeBetweenVertices调用后不需要使用该邻接矩阵,则可以将有关边的数据添加到某个数组中。在你想要使用它之前,请调用你的类的Build(或Rebuild)成员函数(你需要添加这个)。这将实际构建您的邻接矩阵。