2

我对 Scheme 很陌生,我在编写一个函数作为家庭作业的一部分时遇到了麻烦。我有一个图表 G 以列表形式提供给我,格式如下:((node1 node2 weight1) (node3 node4 weight2) ...)。我正在尝试编写一个函数,以这种格式返回此图中所有节点(V)的列表:(node1 node2 node3 ...)。该函数只能将图形(G)作为输入。

所以我想我可以通过将G中每个嵌套列表的第一个和第二个元素添加到V来递归地做到这一点。这是我写的:

    (define nodes-of
      (lambda (G)
        (if (null? G) 
            ()
            (begin (add-to-set (cadar G) (nodes-of (cdr G))) 
                   (add-to-set (caar G) (nodes-of (cdr G))))))

我认为这是错误的,因为第一个递归只涉及 (cadar G) 而第二个涉及 (caar G),返回值将仅由 begin 下的第二个语句设置(如果我没记错的话)。

add-to-set 是我之前为家庭作业编写的一个函数,如果列表中不存在一个元素,它会将它添加到列表中。(例如: add-to-set n S ,这会将 n 添加到 S)

有人可以帮我吗?(顺便说一句,我不允许使用多个 let's、let* 或 set)

4

1 回答 1

3

好吧,您可以递归地执行此操作是对的,并且您的代码非常接近。回想一下,每个递归过程都需要一个您知道答案的基本状态,以及每次递归时降低问题复杂性的方法。

在处理列表的情况下,您的基本情况是空列表,这就是您要检查 null 的原因。然后减少公式将断开列表的一部分,然后调用剩余部分的过程。所以,就像我说的,你很接近。

然后意识到,由于您的数据是定期结构化的,您可以将您的图表视为普通列表。您不需要递归到列表的每个元素,您只需对每个元素执行两个操作并将结果放入列表中。

(define nodes-of
    (lambda (G)
        (if (null? G)   ;<-- have we reached the base case yet?
            '()         ;<-- if yes, return null so our cons will build a list
            (cons (caar G) (cons (cadar G) (nodes-of (cdr G))))))) ;<-- if not, keep building the list by grabbing the things we want from each element, then reducing the list

如果你愿意,你也可以使用let..

(define nodes-of
    (lambda (G)
        (if (null? G)
             '()
             (let ((n1 (caar G))
                   (n2 (cadar G)))
               (cons n1 (cons n2 (nodes-of (cdr G))))))))

在您的情况下,您将使用add-to-setwhere I've used cons。一旦我们达到了基本情况,所有的调用add-to-set都将能够从最后一个开始评估,然后返回堆栈到第一个。

|cons n3 '()           | 2    => (n3)
|cons n2 [result of 2] | 1    => (n2 n3)
|cons n1 [result of 1] | 0    => (n1 n2 n3)
于 2012-05-13T18:16:43.200 回答