我正在使用jGraphT数据结构,我希望能够创建按树中的级别分组的对象列表的ArrayList。
这里是图表
Graph<Obj, DefaultEdge> serviceGraph =
new DefaultDirectedGraph<>(DefaultEdge.class);
serviceGraph.addVertex(a);
serviceGraph.addVertex(b);
serviceGraph.addVertex(c);
serviceGraph.addVertex(d);
serviceGraph.addVertex(e);
serviceGraph.addVertex(z);
serviceGraph.addEdge(a, b);
serviceGraph.addEdge(b, c);
serviceGraph.addEdge(b, z);
serviceGraph.addEdge(b, d);
serviceGraph.addEdge(d, e);
我可以使用BFSIterator
遍历图表,如下所示
A
B
C
Z
D
E
这是我想要的顺序,但我也想知道每个节点的级别,以便我可以将它们分组为
[(A), (B), (C,D,Z) ,(E)]
我在DirectedGraph
API中找不到任何可以轻松获得关卡的内容。当我以BFS方式遍历图形时,如何用其级别标记每个节点?
答案 0 :(得分:1)
编辑:JGraphT现在支持这些功能。使用BFS迭代器,您可以使用getDepth(V v)
方法查询顶点的深度。
============ 旧答案(这几乎是如何实现的):
目前此功能不可用。但是,正在其中一个Pull Requests中进行处理。这个PR可能需要几个月的时间才能合并。然而,与此同时,这个功能相当容易添加。我已经实现了一个新的BFSIterator,它只是对现有BFSIterator的修改。
package org.jgrapht.traverse;
import org.jgrapht.Graph;
import org.jgrapht.Graphs;
import org.jgrapht.graph.DefaultDirectedGraph;
import org.jgrapht.graph.DefaultEdge;
import java.util.ArrayDeque;
import java.util.Deque;
/**
* A breadth-first iterator for a directed or undirected graph which supports querying the depth of a vertex
* in the search tree.
*
* <p>
* For this iterator to work correctly the graph must not be modified during iteration. Currently
* there are no means to ensure that, nor to fail-fast. The results of such modifications are
* undefined.
*
* @param <V> the graph vertex type
* @param <E> the graph edge type
*
* @author Joris Kinable
* @since April 21, 2018
*/
public class BreadthFirstIteratorWithLevel<V, E>
extends CrossComponentIterator<V, E, Integer>
{
private Deque<V> queue = new ArrayDeque<>();
/**
* Creates a new breadth-first iterator for the specified graph.
*
* @param g the graph to be iterated.
*/
public BreadthFirstIteratorWithLevel(Graph<V, E> g)
{
this(g, (V) null);
}
/**
* Creates a new breadth-first iterator for the specified graph. Iteration will start at the
* specified start vertex and will be limited to the connected component that includes that
* vertex. If the specified start vertex is <code>null</code>, iteration will start at an
* arbitrary vertex and will not be limited, that is, will be able to traverse all the graph.
*
* @param g the graph to be iterated.
* @param startVertex the vertex iteration to be started.
*/
public BreadthFirstIteratorWithLevel(Graph<V, E> g, V startVertex)
{
super(g, startVertex);
}
/**
* Creates a new breadth-first iterator for the specified graph. Iteration will start at the
* specified start vertices and will be limited to the connected component that includes those
* vertices. If the specified start vertices is <code>null</code>, iteration will start at an
* arbitrary vertex and will not be limited, that is, will be able to traverse all the graph.
*
* @param g the graph to be iterated.
* @param startVertices the vertices iteration to be started.
*/
public BreadthFirstIteratorWithLevel(Graph<V, E> g, Iterable<V> startVertices)
{
super(g, startVertices);
}
/**
* @see CrossComponentIterator#isConnectedComponentExhausted()
*/
@Override
protected boolean isConnectedComponentExhausted()
{
return queue.isEmpty();
}
/**
* @see CrossComponentIterator#encounterVertex(Object, Object)
*/
@Override
protected void encounterVertex(V vertex, E edge)
{
int depth= (edge == null ? 0 : getSeenData(Graphs.getOppositeVertex(graph, edge, vertex))+1);
putSeenData(vertex, depth);
queue.add(vertex);
}
/**
* @see CrossComponentIterator#encounterVertexAgain(Object, Object)
*/
@Override
protected void encounterVertexAgain(V vertex, E edge)
{
}
/**
* @see CrossComponentIterator#provideNextVertex()
*/
@Override
protected V provideNextVertex()
{
return queue.removeFirst();
}
public int getDepth(V v){
assert getSeenData(v) != null;
return getSeenData(v);
}
public static void main(String[] args){
Graph<String, DefaultEdge> serviceGraph =
new DefaultDirectedGraph<>(DefaultEdge.class);
serviceGraph.addVertex("a");
serviceGraph.addVertex("b");
serviceGraph.addVertex("c");
serviceGraph.addVertex("d");
serviceGraph.addVertex("e");
serviceGraph.addVertex("z");
serviceGraph.addEdge("a", "b");
serviceGraph.addEdge("b", "c");
serviceGraph.addEdge("b", "z");
serviceGraph.addEdge("b", "d");
serviceGraph.addEdge("d", "e");
BreadthFirstIteratorWithLevel<String, DefaultEdge> bfs=new BreadthFirstIteratorWithLevel<String, DefaultEdge>(serviceGraph);
while (bfs.hasNext()) {
String vertex=bfs.next();
System.out.println(String.format("Vertex: %s, depth: %s",vertex, bfs.getDepth(vertex)));
}
}
}
底部的主要功能执行你的例子。输出是:
Vertex: a, level: 0
Vertex: b, level: 1
Vertex: c, level: 2
Vertex: z, level: 2
Vertex: d, level: 2
Vertex: e, level: 3
显然,你必须做一些工作来获得你的阵列,但这应该是从这里直接进行的。两句话: