我在看拓扑排序,看起来很复杂。我想出了这个,它似乎与我能找到的所有例子一起工作。这个逻辑有缺陷吗?
@tsort_array = []
def tsort item, dependencies_array
if index = @tsort_array.index(item)
@tsort_array = @tsort_array.insert(index, dependencies_array).flatten
else
@tsort_array += dependencies_array
@tsort_array << item
end
@tsort_array = @tsort_array.uniq
end
使用http://ruby-doc.org/stdlib-1.9.3/libdoc/tsort/rdoc/TSort.html中的示例会产生相同的结果。
>> tsort 1, [2,3]
=> [2, 3, 1]
>> tsort 2, [3]
=> [3, 2, 1]
>> tsort 3, []
=> [3, 2, 1]
>> tsort 4, []
=> [3, 2, 1, 4]
答案 0 :(得分:0)
这是一个有趣的主意,但不幸的是,该算法存在一些缺陷。
首先,让我们总结一下算法,以确保我们有一个共识:存在一个全局数组tsort_array
。方法tsort
接受一个顶点item
和一个数组dependencies_array
作为输入,该数组保存着item
的依存关系(这意味着必须在顶点item
之前的顶点在拓扑顺序中)。然后,该方法将检查item
中是否已经存在tsort_array
。如果是这样,item
的依赖项将直接插入item
之前。如果不是,则将依赖项附加到tsort_array
的末尾,并在其后附加item
。最后,对tsort_array
进行重复扫描,仅保留每个顶点的第一次出现。在每次调用tsort
之后,应该将到目前为止已添加的图的拓扑顺序包含在tsort_array
中。
如果到目前为止尚未将所有添加的item
添加到tsort_array
(表示对tsort
的每次调用都符合else
的情况,该算法将正常工作。但是,这需要按拓扑顺序添加顶点(即,以前添加的顶点不依赖于当前item
)。因此,您已经必须知道以这种方式添加顶点的拓扑顺序。
在以下情况下,该算法的行为将不正确:
该算法无法检测周期:
> tsort 2, [1]
=> [1, 2]
> tsort 3, [2]
=> [1, 2, 3]
> tsort 1, [3]
=> [3, 1, 2]
这当然不是有效的拓扑顺序,但是算法不指示任何错误。如果假设该算法的输入图始终是非循环的,那就很好。
如果逐步增加顶点的依存关系,该算法将无法正常工作:
tsort 1, []
=> [1]
tsort 3, [2]
=> [1, 2, 3]
tsort 1, [3]
=> [3, 1, 2]
该示例最初添加了没有依赖性的1
。然后添加3
并依赖于2
。这两个顶点将插入1
之后。最后,1
被更新为3
的依赖项。这会将3
移到1
之前,因此也会移到它对2
的依赖之前。
如果假设不会发生此类更新,那就很好,也就是说,始终在一次对tsort
的调用中指定顶点的依存关系。
以下示例排序不正确:
> tsort 4, [2,3]
=> [2, 3, 4]
> tsort 3, [1]
=> [2, 1, 3, 4]
> tsort 2, [3]
=> [3, 2, 1, 4]
通过以4
的顺序指定2,3
的依存关系,然后添加依存关系1 -> 3
,顶点1
将插入到2
和3
,因此在2
之后和3
之前。因此,2
在此步骤之后位于列表的开头。最后,添加依赖项3 -> 2
将3
放在2
之前。因此,3
将在列表的开头,因此在其对1
的依赖之前。