图的连通度

时间:2016-02-03 19:16:28

标签: java graph hashmap hashset

我正在尝试计算图表中每个节点的程度。但是我遇到了麻烦,因为节点是节点类的一部分,我不知道如何将它们转换为Foo。至少我认为这是错的。 这是我一直在尝试的,我有一个String我存储节点,另一个存储边缘(无向图),我需要得到一个包含所有度数的表,然后是节点有这些学位:

Hashset

Eclipse的错误是最后一行,并说:

  

方法put(Integer,List)在Map>类型中;不适用于参数(int,Nodes)。

我愿意尝试其他方法。

修改:public void DegreeList () { List<Nodes> listnodes = new ArrayList<Nodes>(Node); Map <Integer, List<Nodes>> DegreeList = new HashMap<Integer, List<Nodes>>(); for (Nodes n: Node){ int degree=0; for (Edges e: Edge){ if (n.equals(e.start)||n.equals(e.end)){ degree++; DegreeList.put(degree,n); } } } } Nodes是类。 EdgesEdge是存储值的Node。 (抱歉有任何混淆)

2 个答案:

答案 0 :(得分:1)

工作假设

它从您的代码中看起来好像类型Nodes代表单个节点,Node代表Collection个节点。 (并且你的编辑确认了这个假设。)这些名字似乎是倒退的,但我会按照代码对它们的做法进行调查。如果我错了,请纠正我。

即时问题

这里有几个问题,但直接问题非常简单:您的Map期望值List<Nodes>的值,但您只给它一个Nodes个实例。如果您可以将Map更改为番石榴Multimap,请执行此操作。否则,而不是

DegreeList.put(degree, n);

你需要像

这样的东西
List<Nodes> innerList = DegreeList.get(degree);
if (innerList == null) {
    innerList = new ArrayList<Nodes>();
    DegreeList.put(degree, innerList);
}
innerList.add(n);

这样,每个List都会关联degree。您需要这个,因为Map只能为每个键存储一个值。如果您的Map定义为Map<Integer, Nodes>,那么您只能存储一个具有不同学位编号的节点。但这没有任何意义,是吗?任意数量的节点都可以共享相同的度数。因此,您需要MapInteger(代表度)与Collection个节点相关联。您似乎正在使用List作为您选择的CollectionSet可能会更好。

使用Set,您可以将Map定义为

Map<Integer, Set<Nodes>> degreeMap = new HashMap<>();

然后,当到达Map的时候,你会这样做:

Set<Nodes> innerSet = degreeMap.get(degree);
if (innerSet == null) {
    innerSet = new HashSet<>();
    degreeMap.put(degree, innerSet);
}
innerSet.add(n);

在任何一种情况下,您都不再需要listNodes List

其他观察

上面的代码描述了如何将某些内容放入Map。但我们还需要考虑何时将某些内容放入Map。现在,每次有与您正在评估的节点匹配的边缘时,都会将代码插入Map

for (Edges e: Edge){
    if (n.equals(e.start)||n.equals(e.end)){
        degree++;
        DegreeList.put(degree,n); // this shouldn't be here
    }
}
// instead, it belongs here

相反,您应该在每个节点只插入Map一次, 确定节点的度数之后

for (Edges e: Edge){
    if (n.equals(e.start)||n.equals(e.end)){
        degree++;
    }
}

// insert into Map here
Set<Nodes> innerSet = degreeMap.get(degree);
if (innerSet == null) {
    innerSet = new HashSet<>();
    degreeMap.put(degree, innerSet);
}
innerSet.add(n);

答案 1 :(得分:1)

虽然埃里克的答案是正确的,但效率并不高。如果要计算图形中所有节点的度数,并且希望将其存储在以度为单位的地图中,则更快的算法如下:

public static Map<Integer, ArrayList<Node>> nodesByDegree(
        Collection<Edge> edges, Collection<Node> nodes) {

    HashMap<Node, Integer> degrees = new HashMap<>();

    // initialize all nodes with 0 degrees
    for (Node n : nodes) {
        degrees.put(n, 0);
    }

    // calculate all degrees at the same time, in a single pass through E
    for (Edge e : edges) {
        degrees.put(e.start, degrees.get(n.start)+1);
        degrees.put(e.end, degrees.get(n.end)+1);
    }

    // transform into multimap
    HashMap<Integer, ArrayList<Node>> result = new HashMap<>();
    for (Map.Entry<Node, Integer> e : degrees) {
        if ( ! result.containsKey(e.getValue()) {
            result.put(e.getValue(), new ArrayList<Node>());
        }
        result.get(e.getValue()).add(e.getKey());
    }
    return result;
}

请注意,在上面的代码中,edgesEdge的集合,nodesNode的集合。此代码需要O(| V |)+ O(| E |)运行时,它应远低于O(| V |)* O(| E |)