我正在尝试查找图形的两个节点之间的所有路径。我的图表定义为:
(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说内存不足。
有人可以向我解释原因吗?
答案 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)))
在这个版本中,我添加了一个参数来跟踪我已经看过的节点。它会 如果它到达同一节点两次(循环),则发出错误信号。