Java 这看起来像是在图(JGrapthT)中查找没有传出边的顶点的有效方法吗?
我使用JGraphT在内存图中保存大约150000个(或大约150000个)顶点。这是一个有向图,每个顶点都有{0 | 1}条出射边 我想找到并检索没有传出边的顶点集。以下是我的尝试:Java 这看起来像是在图(JGrapthT)中查找没有传出边的顶点的有效方法吗?,java,graph,jgrapht,Java,Graph,Jgrapht,我使用JGraphT在内存图中保存大约150000个(或大约150000个)顶点。这是一个有向图,每个顶点都有{0 | 1}条出射边 我想找到并检索没有传出边的顶点集。以下是我的尝试: import io.vavr.Tuple; import io.vavr.Tuple2; import io.vavr.Tuple3; import io.vavr.control.Option; import org.jgrapht.Graphs; import org.jgrapht.graph.Simple
import io.vavr.Tuple;
import io.vavr.Tuple2;
import io.vavr.Tuple3;
import io.vavr.control.Option;
import org.jgrapht.Graphs;
import org.jgrapht.graph.SimpleDirectedGraph;
import org.jgrapht.graph.concurrent.AsSynchronizedGraph;
public Option<io.vavr.collection.Set<Employee>>
pickEmployeesWithNoSupervisor(Integer companyID) {
// holdingCompany is of type: SimpleDirectedGraph<Employee,String>
// edge is a simple string: "reportingTo"
// Retrieve from a Map, initialized earlier, elsewhere
var holdingCompany = this.allCompanies.get(companyID);
if (holdingCompany == null)
return (Option.none());
else {
var vertices = holdingCompany.vertexSet();
io.vavr.collection.Set<Employee> accumulator = io.vavr.collection.HashSet.empty();
var allNoReportingToEmployees =
io.vavr.collection.HashSet.ofAll(vertices)
.foldLeft(accumulator,(accu,nextEmp) -> {
var hasPredecessors =
Graphs.vertexHasPredecessors(mayBeAKnownCompany,nextEmp);
return (!hasPredecessors ? accu.add(nextEmp) : accu) ;
});
return Option.some(allNoReportingToEmployees);
}
}
public class Employee {
private final Integer empID;
public Employee(Integer empID) {
this.empID = empID;
}
@Override
public boolean equals(Object o) {
// ..
}
@Override
public int hashCode() {
// ..
}
}
导入io.vavr.Tuple;
导入io.vavr.Tuple2;
导入io.vavr.Tuple3;
导入io.vavr.control.Option;
导入org.jgrapht.Graphs;
导入org.jgrapht.graph.SimpleDirectedGraph;
导入org.jgrapht.graph.concurrent.AsSynchronizedGraph;
公共选择权
pickEmployeesWithNoSupervisor(整数公司ID){
//holdingCompany的类型为:SimpleDirectedGraph
//edge是一个简单的字符串:“reportingTo”
//从较早初始化的映射检索其他位置
var holdingCompany=this.allcompanys.get(companyID);
if(holdingCompany==null)
返回(Option.none());
否则{
var vertexts=holdingCompany.vertexSet();
io.vavr.collection.Set acculator=io.vavr.collection.HashSet.empty();
var ALLNOREPORTINGTO员工=
io.vavr.collection.HashSet.ofAll(顶点)
.foldLeft(蓄能器,(累计,下一温度)->{
var=
图.垂直排气分离器(Maybaknowncompany,nextEmp);
返回(!hasPreventors?累计添加(nextEmp):累计);
});
返回选项。部分(全部不向员工报告);
}
}
公营雇员{
私有最终整数empID;
公共雇员(整数empID){
this.empID=empID;
}
@凌驾
公共布尔等于(对象o){
// ..
}
@凌驾
公共int hashCode(){
// ..
}
}
这也许是一种幼稚的尝试。我很想知道是否有更好、更惯用、更高效的方法来实现这一点。我不太确定代码中发生了什么,但下面的方法很好:
Set<Employee> verticesWithoutSucc = myGraph.vertexSet().stream().filter(v -> !Graphs.vertexHasSuccessors(myGraph,v)).collect(Collectors.toSet());
Set verticesWithoutSucc=myGraph.vertexSet().stream().filter(v->!Graphs.vertextsaccessors(myGraph,v)).collect(collector.toSet());
请注意,若要获取所有没有传出圆弧的顶点,必须使用顶点排气分配器(.)
,而不是顶点排气分配器(.)
请注意,vertexhassaccessors
方法只是调用!graph.outgoingEdgesOf(顶点).isEmpty()代码>
这种方法应该是有效的,因为它在O(n)
时间内运行,其中n
是客户数。如果您想要更好的性能,可以在构建图的过程中跟踪所有顶点,而无需向外弧。也就是说,在图形中保留一组所有顶点,每次添加弧(i,j)
,从集合中删除顶点i
。因此,始终可以在固定时间内查询顶点集,而无需输出弧
最后,对于大型图,您可以查看jgrapht opt
包中的优化图实现。与您的代码相比,我的代码太冗长了!:-)我正试图实现同样的目标,是的,您的代码也告诉我,对于类似的任务,通常的方法应该是什么。谢谢让我把它合并到我的代码库中。还要感谢你指出继承者和前任之间的区别。当我直接在软件的页面上写代码时,我把事情搞砸了。再次感谢@乔里斯·金纳布尔