在Scheme中实现深度优先搜索的问题
我试图在Scheme中实现深度优先搜索,但我只能让它部分工作。 这是我的代码:在Scheme中实现深度优先搜索的问题,scheme,Scheme,我试图在Scheme中实现深度优先搜索,但我只能让它部分工作。 这是我的代码: (define (depth-first-search graph node neighbour path dest) (cond ((null? neighbour) #f) ((equal? node dest) path) ((member (car neighbour) path) (depth-first-search graph node (cdr neighbour
(define (depth-first-search graph node neighbour path dest)
(cond ((null? neighbour) #f)
((equal? node dest) path)
((member (car neighbour) path) (depth-first-search graph node (cdr neighbour) path dest))
((memq (car neighbour) (car graph)) (depth-first-search (cdr graph) (car neighbour) (memq (car neighbour) (car graph)) (append path (list (car neighbour))) dest))
(else depth-first-search (cdr graph) path dest)))
这是我的图表,数据结构:
(define complete-graph
'((a b c d e)
(b a c)
(c a b f)
(d a e h)
(e a d)
(f c g i)
(g f h i j)
(h d g j)
(i f g j)
(j g h i)))
这就是我所说的过程:
(depth-first-search complete-graph (caar complete-graph) (cdar complete-graph) (list (caar complete-graph)) 'd)
过程应该以列表的形式返回从起始节点到目的节点的完整路径,但它似乎只适用于某些起始节点和目的节点。如果我以a和c开头,它会返回正确的列表(abc),但是如果我尝试以a和d开头,我会得到f作为回报。因此,可能是算法中的回溯有问题。但是我已经看了太长时间的代码,我真的找不到问题所在。您不想在执行深度优先搜索时更改图形,只想更改当前节点。如果你想纯粹从功能上做事情,让你的功能看起来像:
(define (depth-first-search graph node dest path)
(let dfs ((node node) (path path))
(let ((recur (lambda (node) (dfs node (cons node path)))))
; Write code here
; Recursive calls should use recur, not dfs or depth-first-search
...)))
(返回路径或
#f
作为结果)。您可以使用ormap
(在Racket或SRFI-1中)迭代节点的所有邻居,返回不是#f
的第一个值。在进行深度优先搜索时,您不想更改图形,只想更改当前节点。如果你想纯粹从功能上做事情,让你的功能看起来像:
(define (depth-first-search graph node dest path)
(let dfs ((node node) (path path))
(let ((recur (lambda (node) (dfs node (cons node path)))))
; Write code here
; Recursive calls should use recur, not dfs or depth-first-search
...)))
(返回路径或
#f
作为结果)。您可以使用ormap
(在Racket或SRFI-1中)迭代节点的所有邻居,返回第一个不是#f
的值,假设节点“a有子节点”(b c d e),节点“b有子节点”(a c),节点。。。首先,您需要一个将节点扩展到其子节点的函数
(define (expand graph node)
(let ((c (assq node graph)))
(if c (cdr c) '())))
第二:您必须记住所有访问的节点。通常情况下,hat与路径不同(在本例中可能并不重要)。第三:您需要记住要访问的所有节点(节点扩展过程的结果)。所以定义一个辅助函数
(define (dfs* graph visited border path dest)
如果没有节点可供访问,则不存在道路
(cond ((null? border) #f)
如果边界中的第一个元素等于我们的目的地,那么我们是幸福的
((eq? (car border) dest) (cons (car border) path))
让我们检查所有访问的节点。如果在之前访问了边界中的第一个节点,则继续操作而不进行节点扩展
((memq (car border) visited)
(dfs* graph visited (cdr border) path dest))
否则,展开边界的第一个节点
(else (dfs* graph
(cons (car border) visited)
(append (expand graph (car border)) (cdr border))
(cons (car border) path)
dest))))
使用visited、border和path的起始值调用该帮助器函数:
(define (dfs graph src dst)
(dfs* graph '() (list src) '() dst)
对于呼吸优先搜索:将展开的节点附加到边界的末尾
(else (dfs* graph
(cons (car border) visited)
(append (expand graph (car border)) (cdr border))
(cons (car border) path)
dest))))
编辑:
a) 访问和路径相同,您可以删除其中一个
b) 路径以相反的顺序返回
c) 该过程不正确,路径包含所有访问的节点。但是dfs*结果的后处理将完成这项工作。假设节点“a有子节点”(b c d e),节点“b有子节点”(a c),节点。。。首先,您需要一个将节点扩展到其子节点的函数
(define (expand graph node)
(let ((c (assq node graph)))
(if c (cdr c) '())))
第二:您必须记住所有访问的节点。通常情况下,hat与路径不同(在本例中可能并不重要)。第三:您需要记住要访问的所有节点(节点扩展过程的结果)。所以定义一个辅助函数
(define (dfs* graph visited border path dest)
如果没有节点可供访问,则不存在道路
(cond ((null? border) #f)
如果边界中的第一个元素等于我们的目的地,那么我们是幸福的
((eq? (car border) dest) (cons (car border) path))
让我们检查所有访问的节点。如果在之前访问了边界中的第一个节点,则继续操作而不进行节点扩展
((memq (car border) visited)
(dfs* graph visited (cdr border) path dest))
否则,展开边界的第一个节点
(else (dfs* graph
(cons (car border) visited)
(append (expand graph (car border)) (cdr border))
(cons (car border) path)
dest))))
使用visited、border和path的起始值调用该帮助器函数:
(define (dfs graph src dst)
(dfs* graph '() (list src) '() dst)
对于呼吸优先搜索:将展开的节点附加到边界的末尾
(else (dfs* graph
(cons (car border) visited)
(append (expand graph (car border)) (cdr border))
(cons (car border) path)
dest))))
编辑:
a) 访问和路径相同,您可以删除其中一个
b) 路径以相反的顺序返回
c) 该过程不正确,路径包含所有访问的节点。但是dfs*结果的后处理可以完成这项工作。在
else
子句中调用深度优先搜索之前缺少括号。(追加路径(列表(汽车邻居)))
是一件坏事。在else
子句中调用深度优先搜索之前缺少括号。(追加路径(列表(汽车邻居))
是一件坏事。