给定有向非循环图 G ,有没有办法表示 G ,以便在 O(log | G |)中可以执行以下操作时间?
这些操作对应于 make 之类的程序的基本操作,该程序在执行规则之前计算完整的依赖图:
答案 0 :(得分:1)
我不记得运行时间的复杂性,但也许你可以使用有向图(我最初说 tree 但是某些节点可能有多个父母 - 我不确定如何最好地代表那个??
根据您的要求3,对于没有边缘通向它们的所有节点的集合S,创建"虚拟"的错误是什么?根节点,边缘通向没有父节点的每个节点?这会将要求3更改为"返回G中未标记的节点,该节点具有来自根节点的边缘,导致它#34;。
答案 1 :(得分:0)
这是“计算机编程艺术”第一卷中讨论的拓扑排序算法的一种变体。 1(基本算法),第1节。 2.2.3在Go中实现,实现了所需的功能:
package graph
import "os/exec"
// a user of this package shall initialize each node with the command to be
// run and a set of other nodes that can only be executed when this node has
// been finished. It is assumed that no cycles exist.
type Node struct {
exec.Cmd
incoming int // populated by Execute()
Outgoing []Node
}
type Graph struct {
Nodes []Node
}
// execute a graph
func (g *Graph) Execute() {
var dispatcher = make(chan *Node)
for _, n := range g.Nodes {
for _, nn := range n.Outgoing {
nn.incoming++
}
}
for _, n := range g.Nodes {
if n.incoming == 0 {
go n.run(dispatcher)
}
}
// each node will spawn one task
for _ = range g.Nodes {
n := <-dispatcher
for _, nn := range n.Outgoing {
nn.incoming--
if nn.incoming == 0 {
go n.run(dispatcher)
}
}
}
}
// run the function corresponding to a node and notify when done
func (n *Node) run(dispatcher chan<- *Node) {
n.Cmd.Run()
dispatcher <- n
}
该算法不是一组撤消任务,而是直接生成工人并使用渠道收集它们。