1

我从我的老师那里得到了一些输入文件,我们应该测试该程序。任务是从文件读取,创建一个有向图并打印输出。但是如果有一个周期,我们应该终止程序。拓扑排序和循环

我有一些名为house1和house2的文件。在文件室1中没有任何循环,但在house2中有。但我无法弄清楚为什么我的程序无法找到这个循环。 在这里,我有所有的代码,任何帮助,他说,我应该看是preciated :)

import java.util.*; 
import java.io.*; 
import java.lang.*; 

class Input { 

    public static void main(String[] args) { 

    if (args.length == 0) { 
     System.out.println("enter a filename!"); 
     System.exit(1); 
    } else if (args.length == 1) { 
     String fil = args[0]+".txt"; 
     LesFraFil(fil); 
     // skrivUt(); 
     topSort(); 
    } else { 
     System.out.println("too many parameters, try again..."); 
    } 
    } 

    static int antTask; 
    static Task[] ids; 
    static int tTid; 
    static void LesFraFil(String fil) { 

    int i = 0; 
    int j; 
    try { 

     String lest; 

     Scanner in = new Scanner(new FileReader(fil)); 
     Edge til; 

     int counter = 0; 
     antTask = in.nextInt(); 
     ids = new Task[antTask]; 
     System.out.println(antTask); 
     while (in.hasNextLine()) { 

     lest = in.nextLine(); 
     // hvis tom linje, så hopper den over 
     if(lest.trim().length() == 0) continue; 

     String split[] = lest.split("\\s+"); 
     int id = Integer.parseInt(split[0]); 
     String act = split[1]; 
     int tid = Integer.parseInt(split[2]); 
     int staff = Integer.parseInt(split[3]); 
     int depA = Integer.parseInt(split[4]); 
     tTid += tid; 
     ids[i] = new Task(id, act, tid, staff); 
     j = 4; 

     /* 
     * Lesingen av inputen skal avbrytes når den leser 0. 
     * j er den som holder på hvor langt vi er i split arrayet 
     * når den møter på 0 
     */ 
     while(split[j].compareTo("0") != 0) { 
      int tmp = Integer.parseInt(split[j])-1; 

      // System.out.println(tmp+1 + " Aktivitetens navn : " + act); //+ " tiden aktiviteten tar tid: " + tid + " avhengihet: " + split[j]); 

      j++; 

      if (ids[tmp] == null) { 
      ids[tmp] = new Task(id, act, tid, staff); 
      ids[tmp].visited = true; 
      } 
      ids[i].cntPredecessors++; 
      if(ids[tmp].outEdge == null) { 
      ids[tmp].outEdge = new Edge(ids[tmp], ids[i]); 
      } else { 
      til = ids[tmp].outEdge; 

      while(til.neste != null) { 
       til = til.neste; 
      } 
      // til.neste = new Edge(ids[tmp], ids[i]); 
      } 
     } 
     counter++; 
     i++; 
     } 

     if (antTask == counter) { 
     System.out.println("Lesinga gikk som planlagt av fil: " + fil); 
     System.out.println("Total arbeidstid: " + tTid);// + antTask + " == " + counter); 
     } else { 
     System.out.println("Noe gikk galt avslutter!"); 
     System.out.println(antTask + " || " + counter); 
     System.exit(2); 
     } 
     in.close(); 
    } catch (Exception e) { 
     System.err.println("Dette gikk galt med lesinga: " + e.getMessage()); 
    } 
    } 

    static void topSort() { 
    LinkedList<Task> list = new LinkedList<Task>(); 
    ArrayList<Task> array = new ArrayList<Task>(); 

    Task temp; 
    int totalTime = 0; 
    int counter = 0; 

    for(Task t : ids) { 
     if (t.cntPredecessors == 0) { 
     list.add(t); 

     } 
    } 
    while (!list.isEmpty()) { 
     temp = list.pop(); 
     counter++; 
     array.add(temp); 
     System.out.println("Time " + totalTime + "\t Started task " + temp.id + "\t Staff: " + temp.staff + ", Task done " + temp.id); 
     totalTime += temp.time; 

     for (Task t : ids) { 
     if (--t.cntPredecessors == 0) 
     list.add(t); 
     } 
    } 


    if(counter < antTask) { // checking for loop 
     System.out.println(counter + " != " + antTask); 
     System.out.println("En løkke er funnet i grafen. Avslutter..."); 
     System.exit(0); 
    } 
    System.out.println("Topological sort: " + Arrays.toString(array.toArray()));// den sorterte "arraylisten" 
    System.out.println("Total tid brukt er: " + totalTime); 
    } 

} 

class Task { 

    int id, time, staff; 
    int depA, depB; 
    String name; 
    int eStart, lStart; 
    Edge outEdge; 
    int cntPredecessors; 
    boolean visited; 

    Task(int id, String name, int time, int staff) { 
    this.id = id; 
    this.name = name; 
    this.time = time; 
    this.staff = staff; 
    visited = false; 
    } 

    public String getName() { 
    return name; 
    } 
    public String toString() { 
    return name; 
    } 
} 

class Edge { 

    Task fra, til; 
    Task id, name, time, staff; 
    Edge neste; 
    // Task fra, til; 

    Edge(Task fra, Task til) { //, Task fra, Task til) {//, Task name, Task time, Task staff) { 
    this.fra = fra; 
    this.til = til; 

// this.id = id; 
    // this.fra = fra; 
    // this.til = til; 
    /* this.name = name; 
    this.time = time; 
    this.staff = staff;*/ 
    } 

    public Task getTil() { 
    return til; 
    } 
} 

回答

1

我会在这里写一些一种简单的算法,你在做什么是一个拓扑排序

重要的是,拓扑排序是使用DFS算法O(V + E)

你应该做的是创造某种为每个节点附加属性的(姑且称之为String color并设置它的初始值设定为白色。

当您遍历节点时,将其颜色设置为灰色,并在完成后继续执行DFS,将其颜色设置为黑色。

的一点是 - 如果你访问一个节点与color == graycolor == blackTopological sort chapterIntroduction to Algorithms

发现了一个周期

我建议你阅读,让我们看看你的代码!

您读取输入文件的重要组成部分的东西是在这里:

 while (!list.isEmpty()) { 
      temp = list.pop(); 
      counter++; 
      array.add(temp); 
      System.out.println("Time " + totalTime + "\t Started task " + temp.id + "\t Staff: " + temp.staff + ", Task done " + temp.id); 
      totalTime += temp.time; 

      for (Task t : ids) { 
       if (--t.cntPredecessors == 0) { 
        list.add(t); 
       } 
      } 
     } 

以及用于说它像这样的遗憾,但你的代码是有点乱,没有英文文档,等等,但我认为你缺少你的节点着色的部分,这可能是你找不到一个循环的原因(我想你永远不会结束),因为你错过了为你的节点“着色”,所以没有人知道你已经访问过它们

btw我的“颜色”属性在您的代码中被调用访问(您可以使用布尔值,但是不能像书中那样将其着色为灰色/黑色/白色我张贴在这里)

我猜你在初始化时将其设置为true(你应该把它设置为false和将其设置为true,如果你已经处理/访问节点)

//很抱歉,如果我错了,但它是1A.M.在这里,我只是觉得这可能是问题

// +如果你这样做有向图,并退出如果检测到循环,你和O(V)时间周期检测算法:)