Common Lisp 符号计算引论第八章——递归 学习笔记

1. three rules for solving problem recursively --- take every recursive problem as if it were a journey
1) Know when to stop;
2) Decide how to take one step;
3) Break the journey down into that step plus a smaller journey.

2. 递归模式
1)双测试尾递归
(defun func (x)
     (cond (end-test-1 end-value-1)
               (end-test-2 end-value-2)
               (t (func reduced-x))))

ex
(defun anyoddp (x)
     (cond ((null x) nil)
               ((oddp (first x)) t)
               (t (anyoddp (rest x)))))

2)单测试尾递归

(defun func (x)
     (cond (end-test end-value)
               (t (func reduced-x))))

ex
(defun find-first-atom (x)
     (cond ((atom x) x)
               (t (find-first-atom (first x)))))

3)单测试增量递归
(defun func (x)
     (cond (end-test end-value)
               (t (aug-fun aug-val
                                 (func reduced-x)))))

ex
(defun count-slices (x)
     (cond ((null x) 0)
               (t (+ 1 (count-slices (rest x))))))

3)列表构造递归
(defun func (n)
     (cond (end-test nil)
               (t (cons new-element
                            (func reduced-n)))))

ex
(defun laugh (n)
     (cond ((zerop n) nil)
               (t (cons 'ha (laugh (- n 1))))))

4)多变量递归
(defun func (n x)
     (cond (end-test end-value)
               (t (func reduced-n reduced-x))))

ex
(defun my-nth (n x)
     (cond ((zero p) (first x))
               (t (my-nth (- n 1) (rest x)))))

5)条件增量
(defun func (x)
     (cond (end-test end-value)
               (aug-test (aug-fun aug-val
                                             (func reduced-x))
               (t (func reduced-x))))

ex
(defun extract-symbols (x)
     (cond ((null x) nil)
               ((symbolp (first x))
                (cons (first x)
                          (extract-symbols (rest x))))
               (t (extract-symbols (rest x)))))

6)多重递归
(defun func (n)
     (cond (end-test-1 end-value-1)
               (end-test-2 end-value-2)
               (t (combiner (func first-reduced-n)
                                   (func second-reduced-n)))))

(defun fib (n)
       (cond ((equal n 0) 1)
                 ((equal n 1) 1)
                 (t (+ (fib (- n 1))
                         (fib (- n 2))))))

7)CAR/CDR 递归
(defun func (x)
     (cond (end-test-1 end-value-1)
               (end-test-2 end-value-2)
               (t (combiner (func (car x))
                                   (func (cdr x))))))

(defun find-number (x)
      (cond ((numberp x) x)
                ((atom x) nil)
                (t (or (find-number (car x))
                         (find-number (cdr x))))))

8) 尾递归
尾递归技术
尾递归技术可以消除递归调用之间的“依赖性”,使得空间复杂度为O(1)
尾递归四大特征:
(1)绝大多数尾递归为“主函数+helper”形式,通过帮助函数实现递归主体;
(2)使用额外的变量在递归调用之间传递计算的中间结果;
(3)递归分支是纯的,不包含其他运算;
(4)非递归分支返回的是中间计算的结果;

Keyboard Exercise

(defparameter *family*
  '((colin nil nil)
    (deirdre nil nil)
    (arthur nil nil)
    (kate nil nil)
    (frank nil nil)
    (linda nil nil)
    (suzanne colin deirdre)
    (bruce arthur kate)
    (charles arthur kate)
    (david arthur kate)
    (ellen arthur kate)
    (george frank linda)
    (hillary frank linda)
    (andre nil nil)
    (tamara bruce suzanne)
    (vincent bruce suzanne)
    (wanda nil nil)
    (ivan george ellen)
    (julie george ellen)
    (marie george ellen)
    (nigel andre hillary)
    (frederick nil tamara)
    (zelda vincent wanda)
    (joshua ivan wanda)
    (quentin nil nil)
    (robert quentin julie)
    (olivia nigel marie)
    (peter nigel marie)
    (erica nil nil)
    (yvette robert zelda)
    (diane peter erica)))

(defun father (person)
  (second (assoc person *family*)))

(defun mother (person)
  (third (assoc person *family*)))

(defun parents (person)
  (append (and (father person) (list (father person)))
	  (and (mother person) (list (mother person)))))

(defun children (person)
  (and person
       (mapcar #'first
	       (remove-if-not #'(lambda (rec)
				  (or (equal person (second rec))
				      (equal person (third rec))))
			      *family*))))

(defun siblings (person)
  (set-difference 
   (union (children (father person))
	  (children (mother person)))
   (list person)))

(defun mapunion (func lst)
  (apply #'union (mapcar func lst)))

(defun grandparents (person)
  (mapunion #'parents (parents person)))

(defun cousins (person)
  (mapunion #'children
	    (mapunion #'siblings (parents person))))

(defun descended-from (x y)
  (cond ((null x) nil)
	((member y (parents x)) t)
	(t (or (descended-from (father x) y)
	       (descended-from (mother x) y)))))

(defun ancestors (person)
  (cond ((null person) nil)
	(t (append (parents person)
		   (ancestors (father person))
		   (ancestors (mother person))))))

(defun g-gap-helper (p1 p2 n)
  (cond ((null p1) nil)
	((equal p1 p2) n)
	(t (or (g-gap-helper (father p1) p2 (1+ n))
	       (g-gap-helper (mother p1) p2 (1+ n))))))

(defun generation-gap (p1 p2)
  (g-gap-helper p1 p2 0))


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值