查找图中从一个节点到另一个节点的所有路径

时间:2014-11-10 04:26:32

标签: graph path scheme racket

我正在尝试查找图形的两个节点之间的所有路径。我的图表定义为:

(define-struct graph (nodes neighbors node=?))

(define G1 (make-graph '(A B C D E F G)
              (lambda (n)
                (cond [(symbol=? n 'A) '(B E)]
                      [(symbol=? n 'B) '(E F)]
                      [(symbol=? n 'C) '(D)]
                      [(symbol=? n 'D) '()]
                      [(symbol=? n 'E) '(C F A)]
                      [(symbol=? n 'F) '(D G)]
                      [(symbol=? n 'G) '()]))
              symbol=?)))

我的算法是: 1. main函数返回一个列表列表,所以我在图上做了一个递归 2.将源连接到从邻居到目的地的路径。

(define (find-paths origination destination G)
  (cond
    [(symbol=? origination destination) (list (list destination))]
    [else (local ((define neighbor ((graph-neighbors G) origination))
                  (define candidate (find-paths/list neighbor destination G)))
            (join origination candidate))]))

(define (find-paths/list lo-Os d g)
  (cond
    [(empty? lo-Os) empty]
    [else (local ((define candidate (find-paths (first lo-Os) d g)))
            (cond
              [(empty? candidate) (find-paths/list (rest lo-Os) d g)]
              [else (append (find-paths (first lo-Os) d g)
                            (find-paths/list (rest lo-Os) d g))]))]))

(define (join node list-of-node)
  (map (lambda (n) (cons node n)) list-of-node))

当我测试(find-paths 'A 'E G1)时,它会返回我想要的内容,即(list (list 'A 'E) (list 'A 'B 'E))。但是,当我测试(find-paths 'A 'C G1)时,代码卡住了,而且IDE说内存不足。

有人可以向我解释原因吗?

1 个答案:

答案 0 :(得分:2)

你在'A和'之间有一个无限循环。因为您的功能会测试每个可能的路径 试着从'A到'C,它将测试所有邻居'E让它回到'A并从那里再到'E再次。我添加了displayln来展示这一点。

(find-pahts A C)
(find-pahts B C)
(find-pahts E C)
(find-pahts C C)
(find-pahts C C)
(find-pahts F C)
(find-pahts D C)
(find-pahts G C)
(find-pahts A C)
(find-pahts B C)
(find-pahts E C)
(find-pahts C C)
(find-pahts C C)
(find-pahts F C)
(find-pahts D C)
(find-pahts G C)

正如你所看到的,你陷入了无限循环。它尝试'E'C,这导致'C'C这是一条路径。然后它从“F尝试”D和“G”依次进入“E”F,它们都是死路。然后为'E'的最后一个邻居'A',重新开始。

(define (find-paths origination destination G)
  (local ((define (find-paths-ac orig seen)
            (cond
              [(symbol=? orig destination) (list (list destination))]
              [(member orig seen) empty]   ; you can also return an error here. 
              [else (local 
                      ((define neighbor ((graph-neighbors G) orig))
                       (define candidate 
                         (find-paths/list neighbor (cons orig seen))))
                      (join orig candidate))]))

          (define (find-paths/list lo-Os seen)  
            (cond [(empty? lo-Os) empty]
                  [else (local ((define candidate (find-paths-ac (first lo-Os) seen)))
                          (cond [(empty? candidate) (find-paths/list (rest lo-Os) seen)]
                                [else 
                                  (append candidate
                                    (find-paths/list (rest lo-Os) seen))]))]))) 
    (find-paths-ac origination empty)))

在这个版本中,我添加了一个参数来跟踪我已经看过的节点。它会 如果它到达同一节点两次(循环),则发出错误信号。