Graph Scheme中的图编程

Graph Scheme中的图编程,graph,functional-programming,lisp,scheme,Graph,Functional Programming,Lisp,Scheme,我不熟悉这个计划,已经使用麻省理工学院的计划有一段时间了。我试图了解如何实现流行的图算法,如最短路径算法、BFS、DFS。是否有任何教程可以帮助我理解所涉及的递归以及适当的数据结构?我尝试过用谷歌搜索,但最终没有给我带来好的结果 编辑:我很抱歉之前没有说得更具体。我的问题是关于遍历整个图,而不是找到起始节点和目标节点之间的路径。给定一个图G(V,E),其中V是顶点集,E是边集,从任何节点n开始,生成的路径是什么,以便在遍历结束时,访问所有节点 我在谷歌搜索时发现的大多数实现都带有start和go

我不熟悉这个计划,已经使用麻省理工学院的计划有一段时间了。我试图了解如何实现流行的图算法,如最短路径算法、BFS、DFS。是否有任何教程可以帮助我理解所涉及的递归以及适当的数据结构?我尝试过用谷歌搜索,但最终没有给我带来好的结果

编辑:我很抱歉之前没有说得更具体。我的问题是关于遍历整个图,而不是找到起始节点和目标节点之间的路径。给定一个图G(V,E),其中V是顶点集,E是边集,从任何节点n开始,生成的路径是什么,以便在遍历结束时,访问所有节点

我在谷歌搜索时发现的大多数实现都带有start和goal节点。我的版本(答案之一),选择一个顶点,并访问所有其他顶点

以下图为例:-

1 ----> 2           5
       /|          /|
      / |         / |
     /  |        /  |
    /   |       /   |
   /    |      /    | 
  4<----3 <---6     7
1--->25
/|          /|
/ |         / |
/  |        /  |
/   |       /   |
/    |      /    | 
43),(5->6)和(5->7),我无法在图中表示它们。:-)

1开始穿过的路径可以是:


(1、2、3、4、5、6、7)

广度优先和深度优先搜索都作为示例出现在中,从第节开始。我认为这可能会对您提出的关于递归在图形处理中的使用的问题有最具体的帮助

如果您这样表示图,即作为节点名称及其邻居名称的列表:

(define Graph 
  '((A (B E))
    (B (E F))
    (C (D)))
这样做的好处是,如果允许在列表中为每个键输入多个条目,您甚至可以表示循环图,而无需对数据结构进行破坏性修改(
set cdr!
等)

或者,您不仅可以在列表中存储名称,还可以存储每个邻居的完整表示,这样您就可以在图形中漫游,而无需进行任何名称查找:

(define node-name car)
(define node-children cdr)
(define node-first-child cadr)

(node-first-child (node-first-child node1))

但是,要以这种方式创建循环图,需要使用
set或某种变体。因此,最佳的表示方式实际上取决于应用程序。

花了一些时间,但我终于让它工作起来了!我的输出是通过DFS遍历时访问节点的顺序

请注意,我仍然只是学习计划,我的编程方法可能不是最好的。如果你发现一些错误、不正确或可以更好地表达的东西,请留下评论

    (define (dfs graph)
       (define (dfshelper g unvisited stack path)
          (cond
             ((null? unvisited) path)
                ((null? stack)
                   (dfshelper g
                              unvisited 
                              (append (list (caar unvisited)) stack) 
                              path))
                ((memq (car stack) path) (dfshelper g
                                                    unvisited 
                                                    (cdr stack) 
                                                    path))
                (else (dfshelper g
                                 (cdr unvisited) 
                                 (append (car (neighbours (car stack) g)) (cdr stack)) 
                                 (append path (list (car stack)))))))

   (define (neighbours node g)
      (cond
         ((null? g) '())
         ((equal? node (caar g)) (cdar g))
         (else (neighbours node 
                           (cdr g)))))

   (dfshelper graph  graph '() '()))

示例输入可以是:(dfs’(1(2))(2(3))(3(4))(4(2))(5(36))(6())

此处描述的遍历有一个开始和一个目标节点,如果找到目标节点,则结束。我在实现完整DFS时面临的问题是,“已访问”列表没有传播到更高级别的递归。当然,这是有效的。为了解决这个问题,您需要一个搜索程序,它可以返回有效路径或到目前为止访问过的所有节点的列表。这将允许您避免两次访问相同的节点。感谢gcbenison,您的图形表示非常有用!我很好奇你想编什么代码。具体来说,搜索算法通常包括搜索目标,但看起来您的程序没有。一些目的声明、契约和测试用例会有很大帮助!约翰,我的问题加了一个简短的摘要!如果我遗漏了什么,请告诉我!