如何检测节点网络中是否存在闭环之java实现

1091人阅读 评论(0)

 nodeName： String relList： List curRelIndex： int beforeNode： String

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class GraphAnalysis {
/**
*
* 功能：判断网络中是否存在闭环
* 作者：EugeneJao
* @param nodeCollections
* @return
* @throws Exception
*/
public boolean isContainLoop(Map<String,Map<String,Object>> nodeCollections) throws Exception{
//用map的hash码计算，速度更快
Map<String,String> visitedList = new HashMap<String, String>();
/**
* 初始化"起点
*/
String startNode = getOrigin(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 )){

nodeName = traverse(nodeCollections, nodeName, visitedList);

if(count > 1){
containLoop = containSameNode(visitedList,nodeName.get("nextNode"));
}

count ++ ;

}

return containLoop;

}

/**
*
* 功能：随机获取起始节点
* 作者：EugeneJao
* @param nodeCollections
* @return
*/
@SuppressWarnings("rawtypes")
private String getOrigin(Map<String,Map<String,Object>> nodeCollections){

Set keySet = nodeCollections.entrySet();

Iterator it = keySet.iterator() ;

List<String> keyArr = new ArrayList<String>();

while(it.hasNext()){
Entry tmpSet = (Entry) it.next() ;
}

int randomInteger = (int) (Math.random() * keyArr.size()) ;

return  keyArr.get(randomInteger) ;

}

/**
*
* 功能：访问某个网络节点
* 作者：EugeneJao
* @param nodeCollections
* @param nodeName
* @param visitedList
* @return
* @throws Exception
*/
private Map<String,String> traverse(Map<String,Map<String,Object>> nodeCollections , Map<String,String> nodeName ,
Map<String, String> visitedList) throws Exception{
/**
* 判断前进节点在网络中存不存在
*/
if(nodeName.get("nextNode") != null){
if(!(nodeCollections.containsKey(nodeName.get("nextNode")))){
throw new Exception("节点网络构建异常,网络中不存在节点:" + nodeName);
}
}

if(nodeName.get("curNode") == null || nodeName.get("beforeNode") == null){
throw new Exception("traverse()方法入参异常:curNode和beforeNode不能为空" + nodeName);
}

String nextNodeName =  nodeName.get("nextNode") ;

if( nextNodeName  == null){

nodeName = back(nodeCollections, nodeName);

}else{

}

return nodeName ;

}

/**
*
* 功能：前进至下一个节点
* 作者：EugeneJao
* @param nodeCollections
* @param nodeName
* @param visitedList
* @return
*/
@SuppressWarnings("unchecked")
private Map<String,String> head(Map<String,Map<String,Object>> nodeCollections , Map<String,String> nodeName ,
Map<String, String> visitedList){
String  curNodeName = nodeName.get("nextNode") ; //传入参数的nextNode在本方法中即是当前节点
String beforeNodeName = nodeName.get("curNode") ;//传入参数的curNode在本方法中即是前一节点
Map<String,Object> curNode = nodeCollections.get(curNodeName);
List<String> relList = (List<String>) curNode.get("relList") ;
curNode.put("beforeNode",beforeNodeName) ;//传入参数的beforeNode在本方法中即是当前节点
int curRelIndex = getNextNodeIndex(curNode);
/**
* 获取下一个前进的目标节点名称,当curRelIndex等于relList的长度时，
* 说明当前节点的所有关系节点都遍历完了,已无节点可以前进，只能后退
*/
String nextNodeName = null ;
if(curRelIndex < relList.size()){
nextNodeName = relList.get(curRelIndex) ;
}

/**
* 更新当前节点信息
*/
curNode.put("curRelIndex", curRelIndex);//不能调整顺序值调用getNextNodeIndex()方法后面
nodeCollections.put(curNodeName, curNode);
/**
* 更新nodeName信息
*/
nodeName.put("nextNode", nextNodeName);
nodeName.put("curNode", curNodeName);
nodeName.put("beforeNode", beforeNodeName);
/**
* 更新visitedList信息
*/
visitedList.put(curNodeName,null) ;
return nodeName;

}

/**
*
* 功能：后退至之前的节点
* 作者：EugeneJao
* @param nodeCollections
* @param nodeName
* @return
*/
@SuppressWarnings("unchecked")
private Map<String,String> back(Map<String,Map<String,Object>> nodeCollections , Map<String, String> nodeName){
String  curNodeName = nodeName.get("beforeNode") ; //传入参数的beforeNode在本方法中即是当前节点

Map<String,Object> curNode = nodeCollections.get(curNodeName);
List<String> relList = (List<String>) curNode.get("relList") ;
String beforeNodeName = (String) curNode.get("beforeNode");
/**
* 先更新当前节点beforeNode信息，因为后面要用
*/
curNode.put("beforeNode", beforeNodeName);//不能调整顺序值调用getNextNodeIndex()方法后面

int curRelIndex = getNextNodeIndex(curNode);
/**
* 获取下一个前进的目标节点名称,当curRelIndex等于relList的长度时，
* 说明当前节点的所有关系节点都遍历完了,已无节点可以前进，只能后退
*/
String nextNodeName = null ;
if(curRelIndex < relList.size()){
nextNodeName = relList.get(curRelIndex) ;
}

/**
* 更新当前节点信息
*/
curNode.put("curRelIndex", curRelIndex);//不能调整顺序值调用getNextNodeIndex()方法前面

nodeCollections.put(curNodeName, curNode);
/**
* 更新nodeName信息
*/
nodeName.put("nextNode", nextNodeName);
nodeName.put("curNode", curNodeName);
nodeName.put("beforeNode",beforeNodeName) ;

return nodeName;

}

<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span>*
<span style="white-space:pre">	</span>* 功能：检测是否存在环路
<span style="white-space:pre">	</span>* 作者：EugeneJao
<span style="white-space:pre">	</span>* @param visitedList
* @param curNodeName
* @return
*/
private boolean containSameNode(Map<String, String> visitedList,String curNodeName){

if(visitedList.containsKey(curNodeName)){
return true ;
}

return false;

}

/**
*
* 功能：获取下一节点名称在relList里的索引值
* 作者：EugeneJao
* @param curNode
* @return
*/
@SuppressWarnings("unchecked")
private int getNextNodeIndex(Map<String,Object> curNode){
List<String> relList = (List<String>) curNode.get("relList") ;
int curRelIndex = (Integer) curNode.get("curRelIndex") ;
String beforeNodeName = (String) curNode.get("beforeNode");
String nextNodeName = beforeNodeName ;
//判断是否可以进入while循环，条件一：上一节点名称是否可下一节点名称相同，条件二：数组是否越界
boolean canAdd = beforeNodeName.equals(nextNodeName) && curRelIndex < relList.size()-1 ;
curRelIndex ++ ;
nextNodeName = relList.get(curRelIndex) ;

canAdd = beforeNodeName.equals(nextNodeName) && curRelIndex < relList.size()-1;
}
/**
* 若果经过前面运算后，前一节点名称和下一节点名称依然相同，
* 则说明当前节点的关系节点全都遍历过了,curRelIndex赋值为relList的大小，
* 即说明当前节点的关系节点全都遍历过了，不能前进了，只能后退
*/
if(beforeNodeName.equals(nextNodeName) || relList.size() == 0){
curRelIndex = relList.size() ;
}
return curRelIndex ;
}

}


0
0

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：23652次
• 积分：271
• 等级：
• 排名：千里之外
• 原创：9篇
• 转载：0篇
• 译文：0篇
• 评论：0条
阅读排行