[英]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. 编辑: Nodes
和Edges
是类。 Edge
and Node
are the Hashsets
storing the values. Edge
和Node
是存储值的Hashsets
。 (Sorry for any confusion) (对不起,造成混淆)
It looks from your code as if the type Nodes
represents a single node, and Node
represents a Collection
of nodes. 从您的代码Nodes
,好像Nodes
类型代表单个节点, Node
类型代表Node
的Collection
。 (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. 如果我错了,请纠正我。
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
。
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
. 请注意,在上面的代码中, edges
是Edge
的集合,而nodes
是Node
的集合。 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.