判断是否是有向无环图(是否存在环)
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;
}
本文介绍了一种算法,用于判断一个图是否为有向无环图,并实现拓扑排序。通过计算节点的入度和逐层剥离入度为0的节点来判断图中是否存在环。同时,介绍了如何进行拓扑排序,即对有向无环图的节点进行排序,使得每个节点都位于其所有依赖节点之后。
&spm=1001.2101.3001.5002&articleId=105727922&d=1&t=3&u=83cdcedf8ca64f0d93a9c547cc8536e8)
5万+

被折叠的 条评论
为什么被折叠?



