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))
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-15 11:47:38