方案:从嵌套列表中检索元素

时间:2012-05-13 16:38:12

标签: list graph scheme nested-lists

我对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),并且返回值将仅由开始时的第二个语句设置(如果我没有弄错的话) )。

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

有人可以帮我这个吗? (顺便说一下,我不允许使用多个let,让*或设置)

1 个答案:

答案 0 :(得分: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-set使用的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)