【问题标题】:Is this topological sort in Ruby flawed?Ruby 中的这种拓扑排序有缺陷吗?
【发布时间】:2013-10-05 03:14:32
【问题描述】:

我在看拓扑排序,它看起来很复杂。我想出了这个,它似乎适用于我能找到的所有例子。这个逻辑有问题吗?

@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]

【问题讨论】:

    标签: ruby topological-sort


    【解决方案1】:

    这是一个有趣的想法,但不幸的是该算法存在一些缺陷。

    首先,让我们总结一下算法,以确保我们有一个共同的理解:有一个全局数组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]
      

      通过按2,3的顺序指定4的依赖关系,然后添加依赖关系1 -&gt; 3,顶点1将插入到23之间,所以在2和在3 之前。因此,2 在此步骤之后的列表开头。最后,添加依赖3 -&gt; 2 会将3 放在2 之前。因此,3 将位于列表的开头,因此在它对1 的依赖之前。

    【讨论】:

      猜你喜欢
      • 2012-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多