下面算法可以用来检查有向图G是否有圈:
- 开始时,置图G1=G;
- 如果图G1是空图,则没有圈,算法结束;
- 在图G1中找到一个没有入边(即入度为0)的顶点v。如果找不到这样的顶点v,则图G1必定有圈,从而图G有圈;
- 从图G1中删去顶点v以及所有与顶点v相连的边e,得到新的图G1,转到第二步。
public class CycleJudgeAdvisor {
private List<IVertex> vertexList;
private List<IEdge> edgeList;
public CycleJudgeAdvisor(List<IVertex> vertexList, List<IEdge> edgeList) {
this.vertexList = vertexList;
this.edgeList = edgeList;
}
public boolean hasCycle() {
while (true) {
/*
* 1> If the node list or edge list is empty, no cycle exists and exit.
*/
if (null == vertexList || null == edgeList || 0 >= vertexList.size() || 0 >= edgeList.size())
return false;
/*
* 2> Find one node whose in-degree = 0 (There is no edge whose target is one node).
*/
boolean hasTargetEdge = false;
Iterator<IVertex> nodeIter = vertexList.iterator();
IVertex curNode = null;
while (nodeIter.hasNext()) {
curNode = nodeIter.next();
hasTargetEdge = false;
//Go through each edge to check whether this node has one edge whose target is this node
for (final IEdge edge : edgeList) {
if (edge.getTargetId() == curNode.getId()) {
hasTargetEdge = true;
break;
}
}
//If hasTargetEdge=false, it means that no edge is found whose target is this node
if (!hasTargetEdge)
break;
curNode = null;
}
/*
* 3> If no such node is found, this graph must have one cycle
*/
if (null == curNode) {
return true;
}
/*
* 4> Remove this node from node list and remove all the related edges
*/
vertexList.remove(curNode);
List<IEdge> edgeListCopy = new LinkedList<IEdge>(edgeList);
for ( final IEdge edge : edgeListCopy ) {
if (edge.getTargetId() == curNode.getId() || edge.getSourceId() == curNode.getId()) {
edgeList.remove(edge);
}
}
/*
* 5> Go to step 1 to check the updated graph
*/
}
}
}