Recursion LISP-在旋转列表函数中改进递归到尾部递归

Recursion LISP-在旋转列表函数中改进递归到尾部递归,recursion,functional-programming,lisp,rotation,tail-recursion,Recursion,Functional Programming,Lisp,Rotation,Tail Recursion,我在LISP中有一个递归函数,可以将列表向右或向左旋转,如下所示: (如果数字为正-向左推,如果为负-向右推) 职能: (defun rotate-n (L n) (cond ((= n 0) L) ((> n 0) (rotate-n (rotate-left L) (- n 1))) ((< n 0) (rotate-n (rotate-right L) (+ n 1))))) (旋转方向为n(L n) (cond(=n0)L) ((>n0)

我在LISP中有一个递归函数,可以将列表向右或向左旋转,如下所示:

(如果数字为正-向左推,如果为负-向右推)

职能:

(defun rotate-n (L n)
  (cond ((= n 0) L)
        ((> n 0) (rotate-n (rotate-left L) (- n 1)))
        ((< n 0) (rotate-n (rotate-right L) (+ n 1)))))
(旋转方向为n(L n)
(cond(=n0)L)
((>n0)(旋转-n(向左旋转L)(-n1)))
((
有没有一种方法可以使用尾部递归获得相同的结果? 功能向右旋转和向左旋转工作正常

编辑: 我弄糊涂了。我上面写的函数是尾部递归。如果我没有错的话,这个函数是用于相同目的的正则递归:

(defun rotate-n-r (L n)
  (cond ((= n 0) L)
        ((> n 0) (rotate-left (rotate-n-r L (- n 1))))
        ((< n 0) (rotate-right (rotate-n-r L (+ n 1))))))
(旋转方向为n-r(L-n)
(cond(=n0)L)
((>n0)(向左旋转(旋转-n-rl(-n1)))
(
这是一个尾部递归函数,它可以实现您想要的功能:

(defun rotate-list (list n)
  (cond ((plusp n)
         (rotate-list
          (append (rest list) (list (first list)))
          (1- n)))
        ((minusp n)
         (rotate-list
          (append (last list) (butlast list))
          (1+ n)))
        (t list)))
请注意,它消耗(即分配内存)很多:

不考虑的版本:

(defun nrotate-list (list n )
  (cond ((plusp n)
         (nrotate-list
          (nconc (rest list) (progn (setf (cdr list) nil) list))
          (1- n)))
        ((minusp n)
         (nrotate-list
          (nconc (last list) (nbutlast list))
          (1+ n)))
        (t list)))
在仍为尾部递归时不分配任何内容:

(time (nrotate-list '(5 6 7 8 9) 30))
Real time: 2.3E-5 sec.
Run time: 0.0 sec.
Space: 0 Bytes
(5 6 7 8 9)
请注意,这两个版本在性能方面都非常愚蠢 (他们在每次迭代中扫描列表两次,即。, 它们的时间复杂度是
O(n*length(list))


高效版本将只扫描列表一次(即时间复杂度
O(长度(列表))
),并且不会是递归的。

您有左旋转和右旋转功能吗?因为它们必须被修改/包含在rotate-n中,尾部递归才能工作。你认为用尾部递归可以解决这个问题吗?是的,但我不确定这是一个好主意:无论哪种方法,效果都完全一样。这种方法很像尾部递归:在进行递归调用之前先进行旋转。为什么您认为当前的实现不是尾部递归?cond中的最后一个调用是
rotate-n
@paul在这里拥有它的权限。除非你的意思是你希望你的旋转左和右函数是尾部递归的,这可能是,也可能不是。
(defun nrotate-list (list n )
  (cond ((plusp n)
         (nrotate-list
          (nconc (rest list) (progn (setf (cdr list) nil) list))
          (1- n)))
        ((minusp n)
         (nrotate-list
          (nconc (last list) (nbutlast list))
          (1+ n)))
        (t list)))
(time (nrotate-list '(5 6 7 8 9) 30))
Real time: 2.3E-5 sec.
Run time: 0.0 sec.
Space: 0 Bytes
(5 6 7 8 9)