Recursion LISP-在旋转列表函数中改进递归到尾部递归
我在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)
(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)