简体   繁体   English

图的连通度

[英]Degree of connectivity of a graph

I'm trying to calculate the degree of each node in a graph. 我正在尝试计算图中每个节点的程度。 However I'm having trouble because the nodes are part of the node class and I don't know how to convert them to String . 但是我遇到了麻烦,因为节点是节点类的一部分,并且我不知道如何将它们转换为String At least I think that's what's wrong. 至少我认为这是错误的。 Here's what I've been trying, I have a Hashset where I store the nodes and another one for the edges (undirected graph), and I need to get a table with all the degrees that exists followed by the nodes that have those degrees: 这是我一直在尝试的方法,我有一个Hashset ,用于存储节点,另一个用于存储边缘(无向图),我需要获取一张表,其中包含所有存在的度数,然后是具有这些度数的节点:

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

}

The error from Eclipse is for the last line and says: Eclipse的错误是最后一行,它说:

The method put(Integer, List) in the type Map> is not applicable for the arguments (int, Nodes). Map>类型的put(Integer,List)方法不适用于参数(int,Nodes)。

I'm open to try other approach. 我愿意尝试其他方法。

Edit: Nodes and Edges are classes. 编辑: NodesEdges是类。 Edge and Node are the Hashsets storing the values. EdgeNode是存储值的Hashsets (Sorry for any confusion) (对不起,造成混淆)

Working Assumptions 工作假设

It looks from your code as if the type Nodes represents a single node, and Node represents a Collection of nodes. 从您的代码Nodes ,好像Nodes类型代表单个节点, Node类型代表NodeCollection (And that assumption was confirmed by your edit.) Those names seem backwards, but I'm going by what the code is doing with them. (这些假设已通过您的编辑得到了证实。)这些名称似乎是倒过来的,但是我要按照代码对它们的处理方式进行操作。 Please correct me if I'm wrong. 如果我错了,请纠正我。

The Immediate Question 迫在眉睫的问题

There are several problems here, but the immediate one is pretty simple: your Map expects a value of type List<Nodes> , but you're giving it a single instance of Nodes . 这里有几个问题,但直接的问题很简单:您的Map期望值的类型为List<Nodes> ,但是您只给它一个Nodes实例。 If you can change your Map to a Guava Multimap then please do so. 如果您可以将Map更改为Guava Multimap请这样做。 Otherwise, instead of 否则,代替

DegreeList.put(degree, n);

you'll need something like 你需要类似的东西

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

That way there's a List associated with each degree . 这样,每个degree都有一个List You need this because a Map can only store one value with each key. 你需要这个,因为Map只能存储与每个键的值。 If your Map was defined like Map<Integer, Nodes> then you could only store one node with each distinct degree number. 如果您的Map定义为Map<Integer, Nodes>那么您只能存储每个不同度数的一个节点。 But that doesn't make any sense, does it? 但这没有任何意义,对吗? Any number of nodes could share the same degree number. 任何数量的节点可以共享相同的度数。 So you need a Map that associates an Integer (representing degree) with a Collection of nodes. 因此,您需要一个将Integer (代表度)与节点Collection关联的Map You seem to be using List as your chosen Collection . 您似乎正在使用List作为选择的Collection Set would probably be better. Set可能会更好。

Using Set , you'd define your Map as 使用Set ,您可以将Map定义为

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

Then, when it came time to put something into the Map you'd do it like this: 然后,当需要将某些内容放入Map您将像这样进行操作:

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

In either case you no longer need your listNodes List . 无论哪种情况,您都不再需要listNodes List

Other Observations 其他观察

The code above describes how to put something into the Map . 上面的代码描述了如何将某些东西放入Map But we also need to think about when to put something into the Map . 但是,我们还需要考虑何时将某些内容放入Map Right now you have code inserting into the Map each time there's an edge that matches the node you're evaluating: 现在,每当有一条边与您要评估的节点匹配时,您就将代码插入到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

Instead, you should insert into the Map only once per node, after determining the node's degree: 相反,确定节点的度数 ,每个节点只能插入一次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);

While Erick's answer is correct, it is not very efficient. 尽管埃里克的答案是正确的,但效率不是很高。 If you want to calculate the degree of all nodes in a graph, and you want to store that in a map keyed by degrees, a faster algorithm would be the following: 如果要计算图中所有节点的度数,并且要将其存储在以度数为键的地图中,则可以使用以下更快的算法:

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

Note that, in the above code, edges is a collection of Edge , and nodes is a collection of Node . 请注意,在上面的代码中, edgesEdge的集合,而nodesNode的集合。 This code requires O(|V|) + O(|E|) run-time, which should be much lower than O(|V|) * O(|E|) 此代码需要O(| V |)+ O(| E |)运行时间,该时间应比O(| V |)* O(| E |)低得多

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM