Java判断图中是否存在回路
参考:
https://blog.csdn.net/lezg_bkbj/article/details/11299335
还是上一篇的图
/** * @Author : * @Date : 2021/9/30 16:16 * @Description: 判断一个图是否存在回路 * 方法1:利用减枝的方法 * 如果G为有向图: * 1)首先删除入度为0的点,并且将对应的和该点相连的点的入度-1。 * 2)重复过程1),直到没有入度为0的点,如果还有没被删除的节点,则该有向图一定存在回路 * 如果G为无向图: * 1)首先删除所有度数<=1的点,然后将与这些点相连的所有点的度数-1,然后将所有度数为1的点加入队列中 * 2)对队列中的每个点,重复过程1),如果还有没被删除的节点,那么证明该图一定存在回路。 */ public class Loop { public static void main(String[] args) { WeightGraph weightGraph =new WeightGraph(); Set<String> node = Sets.newLinkedHashSet("v1", "v2", "v3", "v4", "v5", "v6"); List<WeightEdge<String, String, Integer>> edge = Lists.newArrayList(); edge.add(new WeightEdge<>("v1", "v2", 10)); edge.add(new WeightEdge<>("v2", "v3", 7)); edge.add(new WeightEdge<>("v4", "v3", 4)); edge.add(new WeightEdge<>("v4", "v5", 7)); edge.add(new WeightEdge<>("v6", "v5", 1)); weightGraph.setNodes(node); weightGraph.setEdgeList(edge); boolean loop = isLoop(weightGraph); System.out.println(loop); System.out.println("========================="); System.out.println("loop1"); WeightGraph weightGraph1 = WeightGraph.buildGraph(); boolean loop1 = isLoop(weightGraph1); System.out.println(loop1); } /** * 如果有入度为0的点,将它从图中删除,并删除相关的边, * 继续循环知道没有入度为0的点,如果此时图的顶点还不为空,则说明图中有回路 * @param graph * @return */ public static boolean isLoop(WeightGraph graph) { Map<String, Integer> inDegree = getInDegree(graph); //如果有入度为0的点,将它删除,并把所有相关的点入度-1 while (inDegree.containsValue(0)) { System.out.println(inDegree); Set<String> key = getKeyByValue(inDegree, 0); for (String s : key) { graph = graph.removeNode(s); } inDegree = getInDegree(graph); } System.out.println(inDegree); return graph.getNodes().size() != 0; } /** * 返回一条图的入度map * 对无边的节点也要进行初始化,因为判断入度的时候需要 * @param weightGraph * @return */ public static Map<String, Integer> getInDegree(WeightGraph weightGraph) { Map<String, Integer> map = new HashMap<>(); Set<String> nodes = weightGraph.getNodes(); for (String node : nodes) { map.put(node,0); } List<WeightEdge<String, String, Integer>> edgeList = weightGraph.getEdgeList(); for (WeightEdge<String, String, Integer> edge : edgeList) { String end = edge.getEnd(); map.computeIfPresent(end, (k, v) -> v + 1); } return map; } public static <K, V> Set<K> getKeyByValue(Map<K, V> map, V val) { Set<K> set = new HashSet<>(); for (Map.Entry<K, V> entry : map.entrySet()) { if (entry.getValue().equals(val)) { set.add(entry.getKey()) ; } } return set; } }
输出:
{v6=0, v1=0, v2=1, v3=2, v4=0, v5=2} {v2=0, v3=1, v5=0} {v3=0} {} false ========================= loop1 {v6=1, v1=1, v2=2, v3=2, v4=2, v5=2} true
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗