• 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
  • 相关阅读:
    vue学习(五) 访问vue内部元素或者方法
    vue学习(四) v-on:事件绑定
    vue学习(三) v-bind指令
    vue学习(二) 三个指令v-cloak v-text v-html
    vue学习(一)初步了解 vue实例
    Restful 接口开发 完整版
    解决exlipse下 springboot 错误:找不到或无法加载主类
    一张图看懂 SQL 的各种 join 用法
    Rest分页接口开发
    浅谈rest風格的接口开发
  • 原文地址:https://www.cnblogs.com/wangbin2188/p/15357637.html
Copyright © 2020-2023  润新知