本文有向图闭环检测算法和实现由文章《如何检测节点网络中是否存在闭环之java实现》中的无向图闭环检测算法的基础上修改得到,其中修改点如下:
1.修改了数据结构,在原来无向图闭环检测算法的数据结构的基础上,增加了"isFrozen"和"isRoot"属性;其中"isFrozen"属性用于员无向图闭环检测算法中,在多父节点的场景下,由于相同的子节点要遍历两次而造成闭环检测判断的逻辑性错误,同时可以减少算法的开销,默认为false;"isRoot"属性用标识某一节点是否为根节点,默认为fasle。具体数据结构如下表:
属性名 | 值类型 |
nodeName | String |
curRelIndex | int |
beforeNode | String |
relList | List |
isFrozen | boolean |
isRoot | boolean |
2.修改了获取算法起始点的方法,将在无向图闭环算法中随机获取起始点的方式修改为符合有向图的特点的方式-----如果节点集合中有给定根节点,即集合中某个节点的"isFrozen"属性值为true,则选择该属性为根节点,事先给定根节点的方式有助于减少算法开销;若无给定根节点,则算法默认给定一个根节点,该根节点的元素为该集合中的所有的节点,这种方式增加算法的开销
3.修改了进入闭环检测方法的条件----将count > 1 改为 count >= 1 ,其实在无向图中 count >= 1 也无妨。
4.修改了获取从一个节点的关系列表中获取下一节点索引的方法。取消掉了对节点关系列表中与上一节点相同的节点的过滤。
5.修改了back()方法,在back()中增加了对"isFrozen"属性的修改,修改规则是,当一个节点后退时,将改节点的"isFrozen"属性修改为"true"。
6.对traverse()做了一些修改,对调用head()和back()方法的判断中增加了一个判断条件---即若当前节点的isFrozen属性值为true,则后退,不再前进;因为若"isFrozen"属性的值为true,则说明该节点的所有子节点都已经遍历完,而且没有出现闭环的情况,所以可以不用再遍历。
源码如下:
</pre><pre name="code" class="java">/**
*
* 功能:判断有向图中是否存在闭环
* 作者:EugeneJao
* @param nodeCollections
* @return
* @throws Exception
*/
public boolean isContainLoopInDigraph(Map<String,Map<String,Object>> nodeCollections) throws Exception{
//用map的hash码计算,速度更快
Map<String,String> visitedList = new HashMap<String, String>();
/**
* 初始化"起点
*/
String startNode = getOriginInDigraph(nodeCollections);
boolean containLoop = false ;
/**
* 初始化"视野"
*/
Map<String,String> nodeName = new HashMap<String, String>() ;
nodeName.put("nextNode", startNode);
nodeName.put("curNode", startNode);
nodeName.put("beforeNode", startNode);
int count = 0 ;
/**
* 如果当前不含有闭环,并且没有遍历完起点节点的所有分支则进入循环
*/
while(!containLoop
&& !(nodeName.get("beforeNode").equals(nodeName.get("curNode"))
&& nodeName.get("nextNode") == null )){