1

プログラムをテストすることになっている先生からいくつかの入力ファイルを受け取りました。タスクは、ファイルから読み取り、有向グラフを作成し、出力を印刷することです。しかし、サイクルがある場合は、プログラムを終了することになっています。

house1とhouse2という名前のファイルがいくつかあります。ファイルhouse1にはサイクルはありませんが、house2にはサイクルがあります。しかし、なぜ私のプログラムがそのサイクルを見つけられないのか理解できません。ここに私はすべてのコードを持っています、そして私がどこを見るべきかを言う助けはありがたいです:)

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

1 に答える 1

1

ここで、ある種の単純なアルゴリズムを記述します。あなたがしているのはトポロジカルソートです。

重要なことは、トポロジカルソートがDFSアルゴリズムO(V + E)を使用していることです。

あなたがすべきことは、ノードごとにある種の追加の属性を作成することです(それを呼び出してString color、初期値を白に設定しましょう。

ノードを反復処理するときに、色を灰色に設定し、DFSの実行を続行します。完了したら、色を黒に設定します。

重要なのは、次のノードにアクセスした場合、color == grayまたはcolor == blackサイクルを見つけた場合です。

アルゴリズムの概要からトポロジカルソートの章を読むことをお勧めします

そして、あなたのコードを見てみましょう!

入力ファイルから何かを読み、重要な部分はここにあります:

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

このように言って申し訳ありませんが、コードは少し乱雑で、英語のドキュメントなどがありませんが、ノードの色付けの部分が欠けていると思います。これが、サイクルが見つからない理由である可能性があります(そして私はあなたがノードを「着色」するのを逃しているので、あなたが決して終わらないと仮定してください、それであなたがすでにそれらを訪問したことを誰も知りません

ところで、私の「color」属性はコードでvisitedと呼ばれます(ブール値を使用できますが、ここに投稿した本のようにグレー/黒/白に色付けすることはできません)

初期化中にtrueに設定したと思います(すでにノードを処理/訪問している場合は、falseに設定し、trueに設定する必要があります)

//間違っていたら申し訳ありませんが、午前1時です。ここで、これが問題になるかもしれないと思います

// +有向グラフでこれを行い、サイクルを検出した場合は終了すると、O(V)時間でサイクル検出アルゴリズムが取得されます:)

于 2011-11-28T00:11:40.087 に答える