前言:我知道有高质量的图形API可用。我有兴趣写自己的自我改进。
这是我添加节点的功能:
public void addNode(Vertex v, Collection<Edge> neighbors) {
int originalSize = size();
if (head == null) {
head = v;
}
else {
Collection<Edge> inEdges = new ArrayList<Edge>();
inEdges.addAll(neighbors);
traverseGraphToAdd(head, inEdges, v);
}
assert originalSize + 1 == size() :
String.format("adding operation failed. original size: %d, current size: %d", originalSize, size());
}
private void traverseGraphToAdd(Vertex start, Collection<Edge> inEdges, Vertex toAdd) {
Iterator<Edge> iter = inEdges.iterator();
Edge e;
while (iter.hasNext()) {
e = iter.next();
if (e.getSource().equals(start)) {
start.addEdge(e);
iter.remove();
}
else if (! directionalEdges && e.getSink().equals(start)) {
start.addEdge(e);
iter.remove();
}
}
if (inEdges.size() > 0) { //otherwise there's no point in continuing to search
for (Edge arc : start.getOutEdges()) {
traverseGraphToAdd(arc.getSink(), inEdges, toAdd);
}
}
}
大小及其依赖项:
public int size() {
int count = 0;
if (head == null) {
return 0;
}
else {
count = countNodes(head);
}
clearVisited();
return count;
}
private int countNodes(Vertex start) {
int result = 1;
start.setVisited(true);
for (Edge e: start.getOutEdges()) {
if (! e.getSink().isVisited()) {
result += countNodes(e.getSink());
}
}
return result;
}
private void clearVisited() {
if (head != null) {
clearNode(head);
}
}
private void clearNode(Vertex start) {
start.setVisited(false);
for (Edge e: start.getOutEdges()) {
if (e.getSink().isVisited()) {
clearNode(e.getSink());
}
}
}
Edge类:
public Edge(Vertex source, Vertex sink, int weight) {
this.source = source;
this.sink = sink;
this.weight = weight;
}
以下调用有效:
g.addNode(ftw, new HashSet<Edge>()); //first node - empty edges
g.addNode(odp, Arrays.asList(new Edge(ftw, odp, 3))); //link new node to one already in the graph
这不是:
g.addNode(tlt, Arrays.asList(new Edge(tlt, ftw, 2)));
在这一个中,Edge构造函数的第一个参数是不图中已有的节点。我尝试使用以下内容(从上面重复)在addNode中纠正此问题:
if (e.getSource().equals(start)) { /*... */ }
else if (! directionalEdges && e.getSink().equals(start)) { /*... */ }
directionalEdges
是一个类字段,用于确定此图形是否具有方向性。
但是,这会导致断言错误:
Exception in thread "main" java.lang.AssertionError: adding operation failed. original size: 1, current size: 1
这里发生了什么?
答案 0 :(得分:0)
您尝试在示例中创建的图表如下所示:
tlt -> ftw -> odp
创建ftw -> odp
后,您应该(并且我相信)拥有head == ftw
。添加tlt
后,如果您希望遍历算法正常运行,则应该head == tlt
。但是在您向我们展示的代码中,只有一个地方head
被分配,而这只发生在head == null
的条件下,在addNode()的第五行。因此,当您添加head
时,tlt
不会更改,因此traverseGraphToAdd()因此会以ftw
而不是tlt
的形式开始。
但是,这里有一个更普遍的问题,即你的代码无法处理没有root的有向图(也就是说,它们有多个源节点。)考虑如果你想要的话会发生什么像这样的图表:
a -> b <- c
我认为你有这个问题,因为你不再只有一个人。