Tree 使用JgraphT获取树中节点的级别

Tree 使用JgraphT获取树中节点的级别,tree,graph-theory,breadth-first-search,jgrapht,Tree,Graph Theory,Breadth First Search,Jgrapht,我使用的是jGraphT数据结构,我希望能够创建一个ArrayList,其中包含按树中的级别分组的对象列表 这是图表 Graph<Obj, DefaultEdge> serviceGraph = new DefaultDirectedGraph<>(DefaultEdge.class); serviceGraph.addVertex(a); serviceGraph.addVertex(b); serviceGraph.ad

我使用的是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);
这是我想要的顺序,但我也想知道每个节点的级别,以便将它们分组为

[(A), (B), (C,D,Z) ,(E)]

DirectedGraph
API中,我没有找到任何可以轻松获得级别的东西。当我以BFS方式遍历图形时,如何标记每个节点及其级别?

编辑:这些功能现在在JGraphT中得到支持。使用BFS迭代器,可以使用
getDepth(V)
方法查询顶点的深度

============ 旧答案(这就是它的实现方式):

目前此功能不可用。然而,这项工作正在其中一个国家进行。该公关可能需要几个月的时间才能合并。然而,同时,这个特性也很容易添加。我已经实现了一个新的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
显然,您需要做一些工作来获得阵列,但从这里开始应该是直接的。两点意见:

  • 此代码在您的小示例之外没有经过测试,因此可能存在错误
  • 只有在迭代器返回顶点后,才能查询顶点的深度

更新了我的答案:JGraphT现在在BFS迭代器中有一个getDepth(V)方法。要么从Maven下载最新的快照版本,要么等到今年晚些时候的下一个稳定版本。别忘了向上投票。getDepth()方法似乎提供了最短的深度。如果你想要最长的深度,你需要另一种方法。
Vertex: a, level: 0
Vertex: b, level: 1
Vertex: c, level: 2
Vertex: z, level: 2
Vertex: d, level: 2
Vertex: e, level: 3