我正在寻找一个简单的算法来“序列化”有向图。特别是我有一组具有执行顺序相互依赖性的文件,并且我想在编译时找到正确的顺序。我知道这必须是一个相当普遍的事情 - 编译器一直在做 - 但是今天我的谷歌搜索能力很弱。这个“go-to”算法是什么?
拓扑排序(摘自维基百科):
在图论中,有向无环图的一个拓扑排序是其顶点的线性序列,在该序列中每个顶点都排在其所有后继的前面。每个 DAG 都至少有一个拓扑排序。
伪代码:
L ← Empty list where we put the sorted elements
Q ← Set of all nodes with no incoming edges
while Q is non-empty do
remove a node n from Q
insert n into L
for each node m with an edge e from n to m do
remove edge e from the graph
if m has no other incoming edges then
insert m into Q
if graph has edges then
output error message (graph has a cycle)
else
output message (proposed topologically sorted order: L)
我想出了一个相当朴素的递归算法(伪代码):
Map<Object, List<Object>> source; // map of each object to its dependency list
List<Object> dest; // destination list
function resolve(a):
if (dest.contains(a)) return;
foreach (b in source[a]):
resolve(b);
dest.add(a);
foreach (a in source):
resolve(a);
如果图中存在循环,如何存在文件的允许执行顺序呢? 在我看来,如果图中包含循环,那么你就没有解决方案,并且上述算法报告了这一点。
我期望需要这种工具的程序可以以深度优先的方式遍历树,当它们到达叶子节点时,只需处理它(例如编译)并从图中删除它(或将其标记为已处理,并将所有叶子节点处理完毕的节点视为叶子节点)。
只要它是有向无环图,这种简单的基于堆栈的遍历应该很容易。