判斷是否是有向無環圖(是否存在環)

判斷是否是有向無環圖(是否存在環)

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;
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章