我正在制作(或尝试)由Node
和Edge
组成的java中的有向图。此图表示我称之为模块的依赖树(模块在我的程序中扮演一些角色)。某些模块需要在程序中的其他模块之前运行,并且我使用有向图来表示这一点。模块(和Node
)知道其他模块必须在它们之前。
目前我接受并读取一个目录并获取模块的ArrayList,然后将其转换为Node
的ArrayList。我的问题是将这些node
与node
类addEdge(..)
函数相关联。当我调用我的函数(下面的代码)connectNodes(..)
时,我想在node
之间创建边缘对象,这样我就可以遍历整个树,从node
转到{{1}使用node
s。似乎我的edge
方法的工作方式我无法做到这一点。
问题在于,从connectNodes(..)
返回的每个outEdge
对象的inEdge
和HashSet
Node
正确指向connectNodes
name(表示其上下依赖项),但那些Node
个对象没有填充Node
和inEdge
个集合以指向它们上方和下方的outEdge
树。
所以就好像,每个边的每一端指向另一个Node对象的副本,其中包含正确的信息,但是错误的(错误的,我的意思是没有)边集。它们应该指向ArrayList中的其他Node对象。
Node.java
Node
Edge.java
import java.util.ArrayList;
import java.util.HashSet;
public class Node
{
public String name;
public HashSet<Edge> inEdges;
public HashSet<Edge> outEdges;
public ArrayList<String> deps;
public Node(String name, ArrayList<String> deps) {
this.name = name;
inEdges = new HashSet<Edge>();
outEdges = new HashSet<Edge>();
this.deps = deps;
}
public Node addEdge(Node node){
Edge e = new Edge(this, node);
outEdges.add(e);
node.inEdges.add(e);
return this;
}
@Override
public String toString() {
return name;
}
//Used to copy a given node
public Node(Node inNode)
{
this.name = inNode.name;
this.inEdges = (HashSet<Edge>)inNode.inEdges.clone();
this.outEdges = (HashSet<Edge>)inNode.outEdges.clone();
this.deps = inNode.deps;
}
}
问题功能
public class Edge
{
public Node from;
public Node to;
public Edge(Node from, Node to) {
this.from = from;
this.to = to;
}
@Override
public boolean equals(Object obj) {
Edge e = (Edge)obj;
return e.from == from && e.to == to;
}
}
编辑:我认为我的问题在于这个函数意味着克隆数组列表,它没有考虑指向旧节点而不是新节点的边。
private ArrayList<Node> connectNodes(ArrayList<Node> modNodes)
{
//Final output, a directed graph
ArrayList<Node> dirGraph = new ArrayList<Node>();
//For each moduleNode in the argument list
for(int i = 0; i < modNodes.size(); i++)
{
Node curNode = modNodes.get(i);
//Get the modules dependencies
ArrayList<String> curDepNames = curNode.deps;
//For each dependency of this module
for(int j = 0; j < curDepNames.size(); j++)
{
String curDep = curDepNames.get(j);
Node depNode = null;
//For each moduleNode in the argument list
//Find the one that matches this dependency
for(int k = 0; k < modNodes.size(); k++)
{
Node AmodNode = modNodes.get(k);
//If this modules name is the same as the dependency save it
//and break from the loop
if(AmodNode.toString().equals(curDep))
{
depNode = AmodNode;
break;
}
}
// If we didn't find the modules dependency then there is an error
// We are missing a dependency
if(depNode == null)
{
// Throw missing dependency error! ? Do we stop what were doing?
modCheckStat = Messages.SetConfig.MODULE_MISSINGDEP;
return null;
}
//Otherwise connect an edge between the current ModuleNode and its dependency
curNode = curNode.addEdge(depNode);
}
//Add this node and its dependency to the final array
dirGraph.add(curNode);
}
return dirGraph;
}
答案 0 :(得分:1)
首先,当你有HashSet时,总是覆盖equals和hashcode。
除此之外,图形似乎是正确构建的(请注意,您总是返回一个与您的参数具有相同元素的新列表)。您可以使用一些Map来消除最内层的循环(k
)。