您的位置:首页 > 其它

SICP 习题 (2.29) 解题总结:二叉活动体

2015-09-27 14:31 197 查看
SICP 习题 2.29题目很长,实现起来有点繁琐,不过题目不难,花点时间还是容易完成的。
题目引入了一个概念叫二叉活动体,这种东西有一个左分支,有一个右分支,每个分支包括一个长度和一个悬挂物,悬挂物可以是一个数,也可以是另一个二叉活动体。
题中给出了二叉活动体的实现代码:
(define (make-mobile left right)
  (list left right))


也给出了分支的实现代码:
(define (make-branch length structure)
  (list length structure))


题目要求我们写出left-branch和right-branch的过程,用于返回左分支或者是右分支。这个比较简单,因为二叉活动体的实现代码中左分支和右分支是通过list过程组合起来的,将他们取出来的过程就分别是car和cadr,代码如下:
(define (left-branch mobile)
  (car mobile))

(define (right-branch mobile)
  (cadr mobile))


题目还要求我们实现branch-length和branch-structure过程,用于返回分支的长度和悬挂物。同样,实现的时候还是通过car和cadr分别取得,代码如下:
(define (branch-length branch)
  (car branch))

(define (branch-structure branch)
  (cadr branch))


此外,题目还要求我们实现过程total-weight,用于获得一个二叉活动体的总重量。这个实现起来麻烦一点点,需要遍历整棵树,然后统计所有总量,代码如下:
(define (total-weight mobile)
 (if (not (list? mobile))
     mobile

  (+ 
   (branch-weight (left-branch mobile)) 
   (branch-weight (right-branch mobile)))))

(define (branch-weight branch)
  (newline)
  (display "caculating branch-weight")
  (display branch)
  (if (list? branch)
      (if (list? (branch-structure branch))
	  (total-weight (branch-structure branch))
	  (branch-structure branch))
      branch))


接着,题目还要求我们实现一个balance?过程用于检查一个二叉活动体是否是平衡的,平衡的定义书中有说到,就是左分支重量乘以长度等于右分支重量乘以长度,而且所有子树都满足这样的条件。
借助以上实现的方法,检查一个二叉活动体是否平衡可以通过不断递归,不断判断每一个二叉分叉点来实现,代码如下:
(define (balance? mobile)
  (newline)
  (display "evaluating: ")
  (display mobile)
  (if (not (list? mobile))
      (begin
	(display "not list")
	#t
	)
      (let ((left-one (branch-structure (left-branch mobile)))
	    (right-one (branch-structure (right-branch mobile))))
	(newline)
	(display "inner evaluating:")
	(display left-one)
	(display right-one)
	(if (and (balance? left-one)
		 (balance? right-one)
		 (= (* (branch-length (left-branch mobile))
		       (total-weight left-one))
		    (* (branch-length (right-branch mobile))
		       (total-weight right-one))))
	    #t
	    #f))))


最后,题目问我们如果活动体的实现过程中不是使用list过程,而是使用cons过程,我们的程序是否需要很大量的修改。因为我们使用接口封装了不同的获取函数,所以我们的代码不需要大量的修改,只需要改一下那些获取函数就可以了,比如right-branch过程中的cadr修改成cdr就好了:
(define (right-branch mobile)
  (cdr mobile))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: