我不明白为什么我的排序无法正常工作

时间:2019-01-22 14:37:16

标签: c#

我的算法

1)我有一个空的completeTask列表,并与任务进行比较,我试图找到没有依赖性的任务(它是task_e) 什么时候做的,我将添加到完整列表中的第一任务(我只需要一个任务名称,因为我将依赖项的名称和任务名称进行了比较)并将其放在第一位。

2)我们完成了第一个任务-task_e是我们的第一个依赖项。 现在,我必须找到所有具有依赖关系的任务,然后执行。 何时将其添加到completeTask列表中,并执行其他任务

这是我的算法

        public static void Sort(Task[] tasks)
        {
        List<String> completedTaskName = new List<String>();

        Task temp;
        for (int i = 0; i < tasks.Length; i++)
        {
            for (int j = i; j < tasks.Length; j++)
            {
                if (!tasks[j].Dependencies.Except(completedTaskName).Any())
                {
                    temp = tasks[i];
                    tasks[i] = tasks[j];
                    tasks[j] = temp;

                    completedTaskName.Add(tasks[i].Name);
                }
            }
        }
    }

但是我排序时并不能正确显示

new Task("a", "b", "c"),
new Task("b"),
new Task("c", "b"),

2 个答案:

答案 0 :(得分:3)

您是否一定需要在同一数组上应用排序,因为如果可以按顺序完成任务进行复制并追加到列表中,将容易得多。 使用与示例中相同的LINQ方法,您可以简单地根据任务的依赖性将任务从一个列表移至另一个列表,如下所示。

    private static List<Task> Sort(Task[] tasks)
    {
        var completedTasks = new List<Task>();
        var uncompletedTasks = tasks.ToList();
        while (uncompletedTasks.Any())
        {
            var taskToComplete = uncompletedTasks
                .FirstOrDefault(task => !task.Dependencies.Except(completedTasks.Select(x => x.Name)).Any());

            if (taskToComplete == null)
            {
                // Cross dependency between tasks
                Console.WriteLine($"Cross dependency between the tasks: {string.Join(", ", uncompletedTasks.Select(task => task.Name))}");
                break;
            }

            completedTasks.Add(taskToComplete);
            uncompletedTasks.Remove(taskToComplete);
        }

        return completedTasks;
    }

然后只需Sort(tasks)即可代替var sortedTasks = Sort(tasks)

答案 1 :(得分:2)

对OP的评论已经强调了您的代码中的一些问题:

  • 您正在尝试创建排序列表,但您将其丢弃
  • 您正在使用Task作为您的类名,这不是一个好主意,因为.Net框架中已经存在一个Task类。

无论如何,您不应该尝试实现排序算法,.Net框架已经为您实现了(一些)好的算法。不要重新发明轮子

您只需指定如何比较两个对象(在您的情况下为两个Task)。

您可以创建自己的TaskComparer,实现:IComparer<Task>,并在(例如)Linq OrderByList<Task>.Sort中使用比较器

类似的事情应该起作用:

public class TaskComparer: IComparer<Task>
{
    public virtual int Compare(Task t1, Task t2)
    {
        // second task is included in first task dependencies, it should be considered "bigger" than first
        if (t1.Dependencies.Contains(t2.Name))
            return 1;

        // first task is included in second task dependencies, it should be considered "bigger" than second
        if (t2.Dependencies.Contains(t1.Name))
            return -1;

        return 0;
    }
}

public static void Main()
{
    // The following array is an example of specific tasks and dependencies between them.
    // For example the following constructor:
    // new Task("task_a", "task_c")
    // means that task_a may be started only after task_c is complete
    var tasks = new[]
    {
        new Task("task_a", "task_c"),
        new Task("task_b", "task_c"),
        new Task("task_c", "task_e"),
        new Task("task_d", "task_a", "task_e"),
        new Task("task_e"),
    };

    var sortedList = tasks.OrderBy(t => t, new TaskComparer()).ToList();
    foreach (Task t in sortedList)
        Console.WriteLine(t.Name);

    Console.WriteLine();

    // another set of data
    tasks = new Task[]
    {
        new Task("task_a", "task_b", "task_c"),
        new Task("task_b"),
        new Task("task_c", "task_b"),
    };

    sortedList = tasks.OrderBy(t => t, new TaskComparer()).ToList();
    foreach (Task t in sortedList)
        Console.WriteLine(t.Name);
}

输出:

task_e
task_c
task_a
task_b
task_d

task_b
task_c
task_a

在工作中here

查看