判断是否是有向无环图(是否存在环)
package com.xxx; import java.util.*; /** * 判断是否有向无环图 */ public class DagCheck { private static class Node { private String nodeId; private List<Node> childs = new ArrayList<>(); private int indegree = 0; public Node(String nodeId) { this.nodeId = nodeId; } } /** * 判断是否有向无环图 */ public static boolean dagCheck(List<Scene> scenes) { if (scenes.isEmpty()) { return true; } // 生成节点 Map<String, Node> sceneMap = new HashMap<>(); for (Scene s : scenes) { sceneMap.put(s.getSceneId(), new Node(s.getSceneId())); } // 计算入度 for (Scene s : scenes) { for (String d : s.getDepends()) { Node dNode = sceneMap.get(d); dNode.indegree++; sceneMap.get(s.getSceneId()).childs.add(dNode); } } // 入度为0的节点 List<Node> zeroIndegreeList = new ArrayList<>(); for (Node n : sceneMap.values()) { if (n.indegree == 0) { zeroIndegreeList.add(n); } } // 逐层剥离入度为0的节点 return removeZeroIndegree(zeroIndegreeList, sceneMap); } /** * 逐层剥离入度为0的节点 */ private static boolean removeZeroIndegree(List<Node> zeroIndegreeList, Map<String, Node> sceneMap) { // 逐层剥离入度为0的节点 List<Node> childs = new ArrayList<>(); for (Node zn : zeroIndegreeList) { if (!sceneMap.containsKey(zn.nodeId)) { continue; } List<Node> nodeChilds = sceneMap.get(zn.nodeId).childs; for (Node cn : nodeChilds) { // 入度减1 cn.indegree--; } childs.addAll(nodeChilds); // 删除入度为0的节点 sceneMap.remove(zn.nodeId); } // 获取下一层入度为0的节点 Iterator<Node> it = childs.iterator(); while (it.hasNext()) { Node cn = it.next(); if (cn.indegree != 0) { it.remove(); } } // 判断是否为空,否则继续 if (childs.isEmpty()) { // 如果还存在节点,说明存在环路 return sceneMap.isEmpty() ? true : false; } // 递归 return removeZeroIndegree(childs, sceneMap); } public static void main(String[] args) { Scene scene0 = new Scene(); scene0.setSceneId("0"); scene0.getDepends().addAll(Arrays.asList("1", "5")); Scene scene1 = new Scene(); scene1.setSceneId("1"); scene1.getDepends().addAll(Arrays.asList("2", "4")); Scene scene2 = new Scene(); scene2.setSceneId("2"); scene2.getDepends().addAll(Arrays.asList("3")); Scene scene3 = new Scene(); scene3.setSceneId("3"); scene3.getDepends().addAll(Arrays.asList("5")); Scene scene4 = new Scene(); scene4.setSceneId("4"); Scene scene5 = new Scene(); scene5.setSceneId("5"); scene5.getDepends().addAll(Arrays.asList("6", "7")); // scene3.getDepends().addAll(Arrays.asList("1")); Scene scene6 = new Scene(); scene6.setSceneId("6"); Scene scene7 = new Scene(); scene7.setSceneId("7"); List<Scene> scenes = new ArrayList<>(); scenes.addAll(Arrays.asList(scene0, scene2, scene1, scene3, scene4, scene5, scene6, scene7)); System.out.println("DagCheck: " + dagCheck(scenes)); } }
package com.xxx; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; public class TopSearch { /** * 对有向无环图进行拓扑排序 * * @param scenes * @return */ public static List<Scene> topSearch(List<Scene> scenes) { if (scenes.isEmpty()) { return scenes; } List<Scene> result = new ArrayList<Scene>(); LinkedList<String> zeroInNodes = new LinkedList<String>(); Set<String> dependsMap = new TreeSet<String>(); for (Scene a : scenes) { for (String d : a.getDepends()) { //dependsMap.add(a.getSceneId() + "_" + d); dependsMap.add(d + "_" + a.getSceneId()); } } for (Scene scene : scenes) { // 入度为0的节点 if (isZeroInput(scene.getSceneId(), dependsMap)) { zeroInNodes.add(scene.getSceneId()); } } //System.out.println("zeroInNodes:" + zeroInNodes.size()); // 不存在入度为0的节点,那就说明有环 if (zeroInNodes.isEmpty()) { //throw new IllegalStateException("has circle"); return result; } List<String> temp = new ArrayList<String>(); while (!zeroInNodes.isEmpty()) { String take = zeroInNodes.removeFirst(); temp.add(take); for (String s : new ArrayList<String>(dependsMap)) { if (s.startsWith(take + "_")) { dependsMap.remove(s); // String toNode = s.split("_")[1]; if (isZeroInput(toNode, dependsMap)) { zeroInNodes.add(toNode); } } } } Map<String, Scene> sceneMap = new HashMap<String, Scene>(); scenes.forEach(a -> sceneMap.put(a.getSceneId(), a)); temp.forEach(s -> { Scene a = sceneMap.get(s); if (a != null) { result.add(a); } }); return result; } private static boolean isZeroInput(String node, Set<String> depends) { boolean hasDepend = true; for (String s : depends) { if (s.endsWith("_" + node)) { hasDepend = false; } } return hasDepend; } public static void main(String[] args) { Scene scene0 = new Scene(); scene0.setSceneId("0"); scene0.getDepends().addAll(Arrays.asList("1", "5")); Scene scene1 = new Scene(); scene1.setSceneId("1"); scene1.getDepends().addAll(Arrays.asList("2", "4")); Scene scene2 = new Scene(); scene2.setSceneId("2"); scene2.getDepends().addAll(Arrays.asList("3")); Scene scene3 = new Scene(); scene3.setSceneId("3"); //scene3.getDepends().addAll(Arrays.asList("0")); Scene scene4 = new Scene(); scene4.setSceneId("4"); scene4.getDepends().addAll(Arrays.asList("0")); Scene scene5 = new Scene(); scene5.setSceneId("5"); scene5.getDepends().addAll(Arrays.asList("6", "7")); Scene scene6 = new Scene(); scene6.setSceneId("6"); Scene scene7 = new Scene(); scene7.setSceneId("7"); List<Scene> scenes = new ArrayList<>(); scenes.addAll(Arrays.asList(scene0, scene2, scene1, scene3, scene4, scene5, scene6, scene7)); List<Scene> outputScenes = topSearch(scenes); System.out.println(scenes.size()); System.out.println(outputScenes.size()); /*int idx = 0; for (Scene scene : outputScenes) { scene.setPriority(idx); idx++; System.out.println("scene id: " + scene.getSceneId() + " priority: " + scene.getPriority()); }*/ } }
package com.xxx; import java.util.ArrayList; import java.util.List; import lombok.Getter; import lombok.Setter; @Getter @Setter public class Scene { private String sceneId; private List<String>depends = new ArrayList<String>(); private int priority; }