使用列表的方案累积递归

时间:2010-05-05 14:03:43

标签: recursion scheme tail-recursion

如何将列表作为参数传递给函数,该函数以递归方式向其中添加元素,并在递归时不进行修改?

我希望在每个递归级别使用列表,列表中的值会通过更深的递归级别添加。

更具体地说,我想在图表上进行DFS搜索,并且我想在列表中存储我访问过的节点。

3 个答案:

答案 0 :(得分:1)

如果通过将值列入旧列表来构建新列表,则该旧列表不会被修改。

(define old '(1 2 3))
(define new (cons 55 old))

new
>(55 1 2 3)
old
>(1 2 3)

“新”中第一个缺点的“尾巴”是“旧”列表。但是旧的并没有改变。

(cdr new)
> (1 2 3)

答案 1 :(得分:1)

执行此操作的一种方法是返回列表,以便在更高级别的递归时访问它。

另一种方法是将列表存储在递归之外的变量中。换句话说,没有存储在堆栈中。由于为此使用全局变量不是一个好主意,我们需要进行一些局部递归。

以下代码是一种愚蠢的方式来反转列表,但它确实说明了我所说的技术。

(define (letrecreverse lst)
  (letrec ((retlist '())
           (reverse (lambda (lst)
                      (if (null? lst)
                          '()
                          (begin
                            (set! retlist (cons (car lst) retlist))
                            (reverse (cdr lst)))))))
    (reverse lst)
    retlist))

(letrecreverse '(1 2 3 4))
;outputs '(4 3 2 1)

你可以为你的目的采用这种技术吗?

答案 2 :(得分:0)

如果我理解你的问题,这可能是一个解决方案:

;; Just a helper to print the current list.
(define (show list)
  (display "list = ")
  (display list) 
  (newline) 
  (flush-output))

;; Maximum depth of recursion
(define max-recur 5)
;; Original list is backed-up here.
(define orig-list null)

(define (recur list depth)
  (if (null? orig-list) 
      (set! orig-list list))
  (cond ((< depth max-recur)
         (show list)
         (recur (cons (random max-recur) list) (add1 depth)))
        (else orig-list)))

示例运行:

> (recur '(1) 0)
list = (1)
list = (1 1)
list = (2 1 1)
list = (3 2 1 1)
list = (4 3 2 1 1)
(1) ;; In the end you get the original list back.