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的边
Guava类库中的Table是一个双键的Map,可以理解为一个行列式的数据结构。 Table可以用来表示一个映射,其中每个键都有一个与之关联的值,而且这个键需要由两个参数来确定。在Table中,第一个键称为"行键",第二个键称为"列键",而对应的值称为"值"。 Table的实现方式可以看作是一个Map<RowKey, Map<ColumnKey, Value>>的嵌套结构,其中RowKey和ColumnKey分别表示行键和列键,Value表示对应的值。 Table提供了多种视,包括行视、列视、单元格视等,这些视可以方便地进行表格的操作和查询。 下面是一个简单的示例代码: ```java Table<String, String, Integer> table = HashBasedTable.create(); table.put("row1", "col1", 1); table.put("row1", "col2", 2); table.put("row2", "col1", 3); table.put("row2", "col2", 4); System.out.println(table.get("row1", "col1")); // 输出1 System.out.println(table.row("row1")); // 输出{col1=1, col2=2} System.out.println(table.column("col1")); // 输出{row1=1, row2=3} System.out.println(table.cellSet()); // 输出[(row1,col1)=1, (row1,col2)=2, (row2,col1)=3, (row2,col2)=4] ``` 在上面的示例中,我们创建了一个Table对象,并往其中添加了四个元素。然后,我们分别通过get方法、row方法、column方法和cellSet方法获取了对应的视,并输出了它们的内容。 需要注意的是,Table中的行键、列键和值都可以为null,但是在使用时需要特别注意空指针异常的问题。此外,Table中的行键和列键必须实现equals和hashCode方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值