查找带环的有向图中的所有路径

发布于 2024-12-03 04:40:32 字数 1619 浏览 0 评论 0原文

我正在解决一个问题,需要找到有向图中两个节点之间的所有路径。该图可能有循环。

请注意,这种特定的实现方法是迭代 DFS。

我考虑过的几种方法如下 -

  • BFS 似乎没有办法整齐地管理节点之间的这种路径关系。

  • 我没有看到 DFS 递归算法在找到终止节点时传递路径的简单机制。 (如果我实现 Maybe monad 之类的东西,很可能可以完成)。

  • 创建 GRAPH-PARENT 例程。这会在现有代码中增加相当多的改动(和错误)。

抽象地说,需要生成一棵树,以起始节点为根,所有叶子节点为终止节点。从叶子到根的每条路径都是合法路径。这就是递归 DFS 所追踪的结果。

我相当确定可以在这里完成,但我不知道具体如何做。

我已经为该算法定义了一个协议,其中可以为任意对象定义 GRAPH-EQUAL 和 GRAPH-NEXT。

调试节点类型是SEARCH-NODE,并且它具有数据访问器SEARCH-NODE-DATA。

(defun all-paths (start end)
  (let ((stack (list start))
        (mark-list (list start))   ;I've chosen to hold marking information local to all-paths, instead of marking the objects themselves.
        (all-path-list '()))       ; Not used yet, using debug statements to think about the problem
    (do  ()  ;; intializing no variables
     ;; While Stack still has elements
         ((not stack))          
      (let ((item (pop stack)))
    ;; I'm looking at the item.
    (format t "I: ~a~%" (search-node-data item)) 
    (cond ((graph-equal item end)
           (format t "*Q: ~a~%" (loop for var in stack collect (search-node-data var)))
           ;;Unmark the terminal node so we can view it it next time.
           (setf mark-list (remove item mark-list))))

        (loop for next in (graph-next item)
           do        
            (cond ((not (in next mark-list :test #'graph-equal))
                    ;; mark the node
                    (push next mark-list)
                    ;;Put it on the stack
                    (push next stack))))))))

I am working on a problem which requires finding all paths between two nodes in a directed graph. The graph may have cycles.

Notice that this particular implementation approach is an iterative DFS.

Several approaches I've considered are as follows -

  • BFS does not appear to have a way to neatly manage this kind of pathing relationships between nodes.

  • I don't see an easy mechanism for a DFS recursive algorithm to pass up the path when the terminating node is found. (Likely enough it could be done, if I implement a Maybe monad kind of thing).

  • Creating a GRAPH-PARENT routine. That would add a decent amount of churn (& bugs) in the existing code.

Abstractly, what needs to happen is a tree needs to be generated, with the start node as root, and all leafs are the terminating nodes. Each path from leaf to root is a legal path. That is what a recursive DFS would trace out.

I'm reasonably sure it can be done here, but I don't see exactly how to do it.

I've defined a protocol for this algorithm where GRAPH-EQUAL and GRAPH-NEXT can be defined for arbitrary objects.

The debug node type is a SEARCH-NODE, and it has the data accessor SEARCH-NODE-DATA.

(defun all-paths (start end)
  (let ((stack (list start))
        (mark-list (list start))   ;I've chosen to hold marking information local to all-paths, instead of marking the objects themselves.
        (all-path-list '()))       ; Not used yet, using debug statements to think about the problem
    (do  ()  ;; intializing no variables
     ;; While Stack still has elements
         ((not stack))          
      (let ((item (pop stack)))
    ;; I'm looking at the item.
    (format t "I: ~a~%" (search-node-data item)) 
    (cond ((graph-equal item end)
           (format t "*Q: ~a~%" (loop for var in stack collect (search-node-data var)))
           ;;Unmark the terminal node so we can view it it next time.
           (setf mark-list (remove item mark-list))))

        (loop for next in (graph-next item)
           do        
            (cond ((not (in next mark-list :test #'graph-equal))
                    ;; mark the node
                    (push next mark-list)
                    ;;Put it on the stack
                    (push next stack))))))))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

秋风の叶未落 2024-12-10 04:40:32

请参阅计算最短路径的通用方法,了解可以返回图中所有路径的算法(即使存在循环)作为有限时间内边字母表上的正则表达式(假设有限图)。

See A Very General Method for Computing Shortest Paths for an algorithm that can return all paths in a graph (even when there are cycles) as regular expressions over the alphabet of edges in finite time (assuming a finite graph).

神经大条 2024-12-10 04:40:32

您需要将路径列表 (mark-list) 与节点一起传递,因为这是状态的一部分。我在此代码中将其重命名为 path

(defun all-paths (start end)
  (let ((stack (list '(start (start)))) ; list of (node path) elements
        (all-path-list '()))
    (do  ()
      ((not stack))          
      (let ((item (pop stack)))
        (let ((node (first item))
              (path (second item)))
          (format t "I: ~a~%" (search-node-data node)) 
          (cond ((graph-equal node end)
                 (format t "*Q: ~a~%"
                         (loop for var in path
                               collect (search-node-data var)))))
          (loop for next in (graph-next node)
                do        
                (cond ((not (in next path :test #'graph-equal))
                       (push (list next (cons next path)) stack)))))))))

You need to pass the path list (mark-list) along with the nodes, since that is part of the state. I've renamed it path in this code:

(defun all-paths (start end)
  (let ((stack (list '(start (start)))) ; list of (node path) elements
        (all-path-list '()))
    (do  ()
      ((not stack))          
      (let ((item (pop stack)))
        (let ((node (first item))
              (path (second item)))
          (format t "I: ~a~%" (search-node-data node)) 
          (cond ((graph-equal node end)
                 (format t "*Q: ~a~%"
                         (loop for var in path
                               collect (search-node-data var)))))
          (loop for next in (graph-next node)
                do        
                (cond ((not (in next path :test #'graph-equal))
                       (push (list next (cons next path)) stack)))))))))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文