我正在尝试计算图表中每个节点的程度。但是我遇到了麻烦,因为节点是节点类的一部分,我不知道如何将它们转换为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
是类。 Edges
和Edge
是存储值的Node
。 (抱歉有任何混淆)
答案 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>
,那么您只能存储一个具有不同学位编号的节点。但这没有任何意义,是吗?任意数量的节点都可以共享相同的度数。因此,您需要Map
将Integer
(代表度)与Collection
个节点相关联。您似乎正在使用List
作为您选择的Collection
。 Set
可能会更好。
使用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;
}
请注意,在上面的代码中,edges
是Edge
的集合,nodes
是Node
的集合。此代码需要O(| V |)+ O(| E |)运行时,它应远低于O(| V |)* O(| E |)