Algorithm 使用三色算法进行周期检测与使用集合进行周期检测相比,使用其中一种算法比使用另一种算法有什么优势?

Algorithm 使用三色算法进行周期检测与使用集合进行周期检测相比,使用其中一种算法比使用另一种算法有什么优势?,algorithm,graph,depth-first-search,Algorithm,Graph,Depth First Search,有两种看似相似的方法可以检测图形中的循环: 以DFS样式遍历图形,假设所有节点在您第一次访问它们之前都是白色的,使它们变为灰色。在节点上完成所有处理后,将其变为黑色。如果你访问过灰色节点,你就知道你有一个循环 遍历图、DFS样式,并保留一个集合,其中包含DFS堆栈中当前的所有节点(仅用于性能目的)。每次访问节点时,都会将其添加到S中,每次处理完节点后,都会将其从S中删除。如果在任何时候尝试访问已在S中的节点,则存在一个循环 选择一个替代方案比另一个方案有实际优势吗?我可能错过了某种权衡?或者使用

有两种看似相似的方法可以检测图形中的循环:

  • 以DFS样式遍历图形,假设所有节点在您第一次访问它们之前都是白色的,使它们变为灰色。在节点上完成所有处理后,将其变为黑色。如果你访问过灰色节点,你就知道你有一个循环

  • 遍历图、DFS样式,并保留一个集合,其中包含DFS堆栈中当前的所有节点(仅用于性能目的)。每次访问节点时,都会将其添加到S中,每次处理完节点后,都会将其从S中删除。如果在任何时候尝试访问已在S中的节点,则存在一个循环

  • 选择一个替代方案比另一个方案有实际优势吗?我可能错过了某种权衡?或者使用一个或另一个导致完全相同的结果


    感谢

    这两个在概念上是等价的:集合
    S
    完全包含灰色节点,其他方面的算法是相同的

    然而,在实践中,存在着微妙的差异:

    • 如果set
      S
      是基于哈希的实现,那么节点必须是可哈希的。如果散列函数设计不当,或者数据被逆向选择,那么性能可能会受到影响
    • 如果set
      S
      是基于树的实现,则节点必须具有可比性。此外,您不再具有(摊销)常数时间集查找
    • 如果使用颜色,则节点必须有一个“颜色”字段,该字段不能用于其他目的。然而,这提供了最快的“集合查找”,因为它只是一个查找/比较
    • 如果图形是定向的或断开连接的,则必须多次使用DFS(从所有白色节点)。跟踪节点是否已被访问需要第二个集合,因为第一个集合在DFS结束时始终为空。因为实际上有3个节点“状态”,所以需要2组来存储该信息
    在性能关键的情况下,对于线性运行时,颜色方法将具有较小的常数因子。但是如果向节点添加
    color
    字段不是一个选项,那么使用集合是一个不错的选择。如果节点当前实现为
    int
    s或
    String
    s(与可能添加字段的
    Node
    类相反),那么set方法将更易于编码,因为可以避免更改节点的表示形式