递归地将列表的第一个元素附加到列表的其余部分

时间:2013-06-22 22:37:16

标签: list recursion scheme shift

我是一个很新的计划,我想采取一个列表,如(1 2 3 4)并将其发送到一个将返回(4 1 2 3)的函数。第二次运行将返回(3 4 1 2),依此类推,每次调用函数时都会创建一个右移列表。

我想出解决这个问题的第一种方法是递归地交换列表的第一个和最后一个值。所以在方案中我会用列表的cdr附加列表的汽车并递归地将列表的cdr发送回我的函数,直到只能进行最后一次交换。

但是我创建递归函数并不是很好,而且我在使用新语言(例如scheme)时遇到了麻烦。这就是我到目前为止所做的尝试,以便了解我想要去的地方。

(define (rShift lst)
  (if (null? lst)
      '()
      (append (cdr lst (car lst))(rShift (cdr lst)))))

2 个答案:

答案 0 :(得分:0)

您可以做的最好的事情是查看解释器的文档以查看可用的列表函数,并使用它们构建解决方案。例如,在使用list procedures的Racket中,将实现一个简单的解决方案:

(define (rShift lst)
  (cons                             ; stick together the solution
   (last lst)                       ; pick the last item
   (take lst (sub1 (length lst))))) ; pick all items except the last one

我们试一试:

(rShift '(1 2 3 4))
=> '(4 1 2 3)

(rShift (rShift '(1 2 3 4)))
=> '(3 4 1 2)

有无数种方法可以解决这个问题,我会留给您找到最适合您需求的方法,但请记住 - 总是尝试解决已经可以使用的构建块的问题,以及不要重新发明轮子。只是为了好玩,这是另一种方式,使用reverse

(define (rShift lst)
  (let ((rev (reverse lst)))
    (cons (car rev)
          (reverse (cdr rev)))))

答案 1 :(得分:0)

如果你打算做一个递归解决方案,那么你需要问问自己“问题的哪个部分可以解决,留下相同但较小的部分问题仍然存在”和“我如何结束递归”。

对于您的问题,当您有最后一个元素然后用于添加到列表的前面时,您将结束递归。问题是用“右移”递归是不够的,因为你需要保留列表以便将最后一个元素放在它的前面。

所以:

(define (right-shift list)
  (if (null? list)
      '()
      (let shifting ((list list) (result '()))
        (if (null? (cdr list))
            (cons (car list) (reverse result))
            (shifting (cdr list) (cons (car list) result))))))
;; Hey look, it compiles... gosh I love interactive languages.

;; ... and works.
> (right-shift '(1 2 3 4))
(4 1 2 3)
> (right-shift (right-shift '(1 2 3 4)))
(3 4 1 2)