Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 支持循环依赖的拓扑排序_C#_Sorting_Topological Sort - Fatal编程技术网

C# 支持循环依赖的拓扑排序

C# 支持循环依赖的拓扑排序,c#,sorting,topological-sort,C#,Sorting,Topological Sort,考虑以下依赖关系(其中A-->B意味着B依赖于A,因此A实际上是“父级”) 更形象地说: A | ---------- | | B C | ----------- | | D E A | B <--> C | | D E 拓扑排序算法将返回如下结果: ABCDE 我已经找到了这方面的代码(和),但它们都不支持周期依赖性。我认为这种情况可能发生

考虑以下依赖关系(其中
A-->B
意味着B依赖于A,因此A实际上是“父级”)

更形象地说:

    A
    |
----------
|        |
B        C
         |
    -----------
    |         |
    D         E
A
|
B <--> C
|      |
D      E
拓扑排序算法将返回如下结果:

ABCDE
我已经找到了这方面的代码(和),但它们都不支持周期依赖性。我认为这种情况可能发生:

A --> B
B --> C
B --> D
C --> B
C --> E
以图形方式:

    A
    |
----------
|        |
B        C
         |
    -----------
    |         |
    D         E
A
|
B <--> C
|      |
D      E
所以,重要的是,这不一定是一棵树。我可以有任意的图形。事实上,并非所有节点都必须相互连接。

事实上,您需要图形的打印输出

链接的wikipedia页面列出了执行此操作的算法


还有一个问题,所以从正确思考问题开始。你没有树。你有一个任意的图形

考虑到这一点,您可能首先需要做的是删除循环中的一条边(好的,将该边标记为“在进行拓扑排序时忽略此项”)来删除和打断它们


删除所有循环后,您可以将TopLogic sort应用于其余节点和弧。

首先,如果您有一个可以询问“您依赖什么”的图形,则概念上会更简单?我假设我们有一个图,其中从a到B的有向边表示“a依赖于B”,这与你的陈述相反

我对你的问题有些困惑,因为忽略循环的拓扑排序实际上与常规拓扑排序相同。我将开发算法,以便您可以根据需要处理循环;也许这会有所帮助

这种分类的思想是:

  • 图是一组节点,每个节点都有一组邻居。正如我所说,如果一个节点a有一个邻居B,那么a依赖于B,所以B必须发生在a之前

  • 排序采用图形并生成节点的排序列表

  • 在排序操作期间,将维护一个字典,该字典将每个节点映射到三个值中的一个:活的、死的和不死的。尚未处理活动节点。已处理死节点。正在处理一个不死节点;它不再活着,但还没有死

  • 如果遇到死节点,可以跳过它;它已经在输出列表中

  • 如果遇到活动节点,则递归处理它

  • 如果你遇到一个不死节点,那么它是一个循环的一部分。做你喜欢做的事。(如果周期非法,则产生错误;如果周期合法,则将其视为无效,等等)



有意义吗?

三年后编辑:自从我在2014年第一次实现它以来,我偶尔会回到这里。当我第一次发布这个答案的时候,我对它并没有很好的理解,所以这个答案太复杂了。排序实际上非常容易实现:

公共类节点
{
公共int数据{get;set;}
公共列表子项{get;set;}
公共节点()
{
Children=新列表();
}
}
公共类图
{
公共列表节点{get;set;}
公共图()
{
节点=新列表();
}
公共列表拓扑排序()
{
var results=新列表();
var seen=新列表();
var pending=新列表();
访问(节点、结果、已查看、待定);
返回结果;
}
私有无效访问(列表图、列表结果、列表失效、列表待定)
{
//图中的每个节点
foreach(图中的var n)
{
//如果节点已被访问,则跳过
如果(!dead.Contains(n))
{
如果(!pending.Contains(n))
{
待决。添加(n);
}
其他的
{
WriteLine(String.Format(“检测到循环(节点数据={0})”,n.Data));
返回;
}
//对当前节点的每个子节点递归调用此函数
访问(n.儿童、结果、死亡、待定);
如果(待定。包含(n))
{
待定。删除(n);
}
加上(n);
//使其通过了重现部分,因此不再有依赖项。
//因此,将节点追加到输出列表中。
结果:添加(n);
}
}
}
}

假设此图只有一个起点。考虑到它是一个依赖关系图,我强烈怀疑这种情况。事实上,谈论一棵树太快了。尽管如此,呼吸先穿过图形是一个典型的问题,如果我添加了
a-->B-->C-->a
?请参阅“我的编辑”。@Peter:选择任意节点作为根节点,这样每个节点都可以从您选择的节点访问。在你的例子中,你可以选择A,B,或C。事实上,我没有树,它可以是任意的图。我会调查的。事实上,“Topo”代表“拓扑学”,而不是“拓扑学”。我建议看一下这里,因为这似乎是同一类别中回答最多的问题:
function topoSort(graph) 
  state = []
  list = []
  for each node in graph
    state[node] = alive
  for each node in graph
    visit(graph, node, list, state)
  return list

function visit(graph, node, list, state)
  if state[node] == dead
    return // We've done this one already.
  if state[node] == undead
    return // We have a cycle; if you have special cycle handling code do it here.
  // It's alive. Mark it as undead.
  state[node] = undead
  for each neighbour in getNeighbours(graph, node)
    visit(graph, neighbour, list, state)
  state[node] = dead
  append(list, node);