我是一個超級 CL 初學者,我對以下任務感到非常困惑:
定義一個遞回函式,從給定串列
shorten中洗掉最后n 個元素。該函式應在最后回傳縮短的串列。例如:
(shorten 5 '(1 2 3 4 5 6 7 8 9 10)) => (1 2 3 4 5)
也許有人可以幫助我。
非常感謝!
uj5u.com熱心網友回復:
我這樣做的計劃是,p0指向串列的開始,沿著串列n時間走,然后得到p2; 然后使用p1最初等于并p0沿著串列每次遞增直到串列末尾的點;然后; 最后回傳。p1p2p2(rplacd p1 nil)p0
針對極端情況和非一錯誤調整上述內容。
串列的“指標”的重復遞增(setf p2 (cdr p2))等可以使用遞回函式進行編碼,通過將其(cdr p2)作為引數呼叫。
uj5u.com熱心網友回復:
這是基于 Will Ness 的絕招的答案。您可能無法將此作為家庭作業提交。 tconc來自 Interlisp,至少它的名字如此。
(defun empty-tconc ()
;; make an empty accumulator for TCONC
(cons nil nil))
(defun tconc (v into)
;; destructively add V to the end of the accumulator INTO, return
;; INTO
(if (null (car into))
(setf (car into) (list v)
(cdr into) (car into))
(setf (cdr (cdr into)) (list v)
(cdr into) (cdr (cdr into))))
into)
(defun tconc-value (into)
;; Retrieve the value of an accumulator
(car into))
(defun shorten (l n)
;; shorten list L by N elements at the end
(check-type n (integer 0))
(shorten-loop l l n (empty-tconc)))
(defun shorten-loop (l1 l2 n into)
(if (zerop n)
(if (endp l2)
(tconc-value into)
(shorten-loop (rest l1) (rest l2) n
(tconc (first l1) into)))
;; Note (rest '()) is '() in CL, hence this abuse
(shorten-loop l1 (rest l2) (1- n) into)))
uj5u.com熱心網友回復:
這個問題的解決方案是尾呼叫遞回。也就是說,當我們做每一步的時候,我們呼叫函式,減少計數和輸入串列,更新一個結果。完成后,我們回傳結果。我們知道我們完成了,因為計數器為零或輸入串列已用盡。
(defun shorten (n lst &optional (res '()))
(if (or (= n 0) (null lst))
(reverse res)
(shorten (1- n) (cdr lst) (cons (car lst) res))))
(shorten 5 '(1 2 3 4 5 6 7 8 9 10)) ; (1 2 3 4 5)
(shorten 1 '(1 2 3 4 5 6 7 8 9 10)) ; (1)
(shorten 11 '(1 2 3 4 5 6 7 8 9 10)) ; (1 2 3 4 5 6 7 8 9 10)
(shorten 0 '(1 2 3 4 5 6 7 8 9 10)) ; NIL
(shorten 5 '()) ; NIL
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/532414.html
標籤:列表递归链表通用语言
下一篇:C編程遞回分段錯誤
