使用循环查找有向图中的所有路径

时间:2011-09-07 02:47:10

标签: algorithm common-lisp

我正在研究一个需要在有向图中查找两个节点之间的所有路径的问题。图表可能有周期。

请注意,此特定实现方法是迭代DFS。

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

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

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

  • 创建GRAPH-PARENT例程。这将在现有代码中添加相当数量的流失(& bugs)。

抽象地说,需要生成的是需要生成树,以节点为根,所有叶子都是终止节点。从叶到根的每条路径都是合法的路径。这就是递归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))))))))

2 个答案:

答案 0 :(得分:1)

请参阅A Very General Method for Computing Shortest Paths以获得一种算法,该算法可以将图中的所有路径(即使有周期)返回为有限时间内边缘字母表上的正则表达式(假设有限图)。

答案 1 :(得分:-1)

您需要将路径列表(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)))))))))