拓扑排序和循环

发布于 2024-12-18 10:28:14 字数 5016 浏览 2 评论 0原文

我从老师那里得到了一些输入文件,我们应该用它们来测试程序。任务是从文件中读取,创建有向图并打印输出。但如果存在循环,我们应该终止程序。

我有一些名为 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;
    }
}

I've got some input files from my teacher wich we are supposed to test the program with. The task is to read from file, create a directed graph and print out the output. But if there is a cycle we are supposed to terminate the program.

I've got some files named house1 and house2. in the file house1 there isn't any cycles, but in house2 there is. But I can't figure out why my program can't find that cycle.
Here I have all the code, and any help saying where I should be looking at is 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;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

彩虹直至黑白 2024-12-25 10:28:14

我将在这里写一些简单的算法,你正在做的是拓扑排序

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

你应该做的是为每个节点创建某种附加属性(我们将其称为String color,并将其初始值设置为白色。

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

黑色 要点是 - 如果您访问带有 color == greycolor == 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);
                }
            }
        }

很抱歉这样说,但是你的代码有点混乱,没有英文文档等,但我认为你错过了为节点着色的部分,这可能就是为什么你找不到循环的原因(我想你永远不会结束),因为你错过了给你的节点“着色”,所以没有人知道你已经访问过它们,

顺便说一句我的“颜色”属性被称为在您的代码中访问过(您可以使用布尔值,但你不能像我在这里发布的书中那样将其着色为灰色/黑色/白色)

我猜你在初始化期间将其设置为 true (你应该将其设置为 false 并设置为 true 如果你已经处理/访问了该节点)

// 抱歉,如果我错了,现在是凌晨 1 点。在这里,我只是认为这可能是问题所在

// + 如果您在有向图上执行此操作,并在检测到循环时退出,您将在 O(V) 时间内获得循环检测算法:)

I'll write here some kind of simple algorithm, what you are doing is a topological sort

Important thing is that topological sort is using DFS algorithm O(V+E)

What you should do is to create some kind of additional attribute for each Node (let's call it String color and set it's initial value to white.

As you'll iterate through your nodes, set it's color to gray, and continue doing a DFS, after it's done, set it's color to black.

The point is - if you visit a node with color == gray or color == black you found a cycle

I recommend reading a Topological sort chapter from Introduction to Algorithms

And let's see your code!

You read something from input file and important part is here:

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

well sorry for saying it like this, but your code is little messy, without english documentation, etc. but I think you are missing the part of coloring your nodes, that can be the reason why you can't find a cycle ( and I suppose you never end ) , because you miss to "color" your nodes, so nobody knows that you have already visited them

btw my "color" attribute is called visited in your code (you can use boolean but then you can't color it to gray/black/white as in the book I posted here)

I guess you set it to true during initialization (you should set it to false and set it to true if you have already processed/visited the node)

// Sorry if I'm wrong but it's 1A.M. here, I just think this might be the issue

// + if you do this on directed graph, and exit if you detect cycle, you get and cycle detection algorithm in O(V) time :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文