Guava学习(三)-图

在计算机科学中,一个图就是一些顶点的集合,这些顶点通过一系列边结对(连接)。顶点用圆圈表示,边就是这些圆圈之间的连线。顶点之间通过边连接。关于图数据结构的介绍可以参照 数据结构-图

Guava-Graph

特性:a)顶点唯一; b)支持有向边和无向边; c)边只能通过两个顶点隐式定义; d)不支持并行边。

示例图如下:

在这里插入图片描述
使用对应构建类GraphBuilder来构建Graph实例

        MutableGraph<Integer> graph1 = GraphBuilder.directed() //指定为有向图
                .nodeOrder(ElementOrder.<Integer>insertion()) //节点按插入顺序输出
                //(还可以取值无序unordered()、节点类型的自然顺序natural())
                .expectedNodeCount(20) //预期节点数
                .allowsSelfLoops(true) //允许自环
                .build();

在Builder中并没有包含复杂的构造逻辑,而只是简单设置了几个全局属性而已(如输出所示:是否允许自环、是否有向等);build()接口为最终的构建接口,返回一个MutableGraph接口类型的返回值,此处返回的是其实现子类ConfigurableMutableGraph,内部通过一个ConfigurableMutableValueGraph实例来实现(所有的方法都调用该实例的方法实现)的,因为ValueGraph包含了Graph的全部功能,可以猜测到设计者也因此复用了同一套实现方案(ConfigurableMutableValueGraph)。

增加节点以及连接边

        Integer N1 = 1;
        Integer N2 = 2;
        Integer N3 = 3;
        Integer N4 = 4;

        //插入边(默认会将节点加入graph中)
        graph1.putEdge(N2, N3);
        graph1.putEdge(N1, N3);
        graph1.putEdge(N1, N2);
        graph1.putEdge(N2, N2);
        graph1.addNode(N4);

        //返回图中所有的节点(顺序依赖nodeOrder)
        Set<Integer> nodes = graph1.nodes();
        System.out.println("graph1 nodes count:" + nodes.size() + ", nodes value:"
                + nodes);

        //返回图中所有的边集合
        Set<EndpointPair<Integer>> edges = graph1.edges();
        System.out.println("graph1 edge count:" + edges.size() + ", edges value:"
                + edges);

返回结果:

graph1 nodes count:4, nodes value:[2, 3, 1, 4]
graph1 edge count:4, edges value:[<2 -> 2>, <2 -> 3>, <1 -> 2>, <1 -> 3>]

获取节点的前趋列表

Set<Integer> predecessors = graph1.predecessors(N2); //获取N2的前趋
System.out.println("graph1 node:" + N2 + " predecessors:" + predecessors);

输出:

graph1 node:2 predecessors:{1,2}

注:对于允许自环的图allowsSelfLoops(true)中,一条自环边在有向图中既是前趋也是后继,既是入度也是出度。

获取节点的后继列表

graph1.putEdge(N2, N4); //图上面示例图中红色边所示,动态增加了一条边
Set<Integer> successors = graph1.successors(N2); //获取N2的后继
System.out.println("add edge of (" + N2 + "->" + N4 + ") after graph1 node:"
                + N2 + " successors:" + successors);

输出:

add edge of (2->4) after graph1 node:2 successors:[4, 2, 3]

获取节点的邻接点列表(包括前趋和后继)

Set<Integer> adjacents = graph1.adjacentNodes(N2); //获取N2的邻接点
System.out.println("graph1 node: " + N2 + ", adjacents: " + adjacents);

输出:

graph1 node: 2, adjacents: {4,1,2,3}

获取节点的度(入度和出度)

System.out.println("graph1 node: " + N2 + ", degree: " + graph1.degree(N2)
         + ", indegree: " + graph1.inDegree(N2)
         + ", outdegree: " + graph1.outDegree(N2)); //N2的度、入度、出度

输出:

graph1 node: 2, degree: 5, indegree: 2, outdegree: 3 //自环既是入度也是出度

判断顶点连通性(是否有直连边)

final boolean connecting23 = graph1.hasEdgeConnecting(N2, N3); //N2&N3是否连通
final boolean connecting14 = graph1.hasEdgeConnecting(N1, N4); //N1&N4是否连通
System.out.println("graph1 node " + N2 + " & " + N3 + " connecting: " + connecting23
                + ", node " + N1 + " & " + N4 + " connecting: " + connecting14);

输出:

graph1 node 2 & 3 connecting: true, node 1 & 4 connecting: false

转换成不可变graph(Immutable类型)**

ImmutableGraph<Integer> immutableGraph = ImmutableGraph.copyOf(graph1);
nodes = immutableGraph.nodes(); //返回图中所有的节点(顺序依赖nodeOrder)
System.out.println("immutable graph nodes count:" + nodes.size()
                + ", nodes value:" + nodes);

输出:

immutable graph nodes count:4, nodes value:{2,3,1,4} //同被拷贝图顺序

判断是否存在环(第一个顶点和最后一个顶点相同的路径称为环)

final boolean cycle = Graphs.hasCycle(graph1);
System.out.println("graph1 has cycle: " + cycle);

输出:

graph1 has cycle: true //因为N2节点存在一条自环,如果去掉则不存在环

获取节点的可到达列表(获取能访问到的节点结合,不单指直连边)

Set<Integer> reachNodes = Graphs.reachableNodes(graph1, N2); //N2的可达列表
Log.d(TAG, "graph1 node: " + N2 + ", reachNodes: " + format(reachNodes));

输出:

graph1 node: 2, reachNodes: {2,4,3} //N2不存在能访问到N1的边
发布了44 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/hxyascx/article/details/99550530
今日推荐