2.29
练习 2.29 一个二叉活动体由两个分支组成,一个是左分支,另一个是右分支。每个分支是一个具有确定长度的杆,上面或者吊着一个重量,或者吊着另一个二叉活动体。我们可以用复合数据对象表示这种二叉活动体,将它通过其两个分支构造起来(例如,使用list):
(define (make-mobile left right)
(list left right))
分支可以从一个length(它应该是一个数)再加上一个structure构造出来,这个structure或者是一个数(表示一个简单重量),或者是另一个活动体:
(define (make-branch length structure)
(list length structure))
a)请写出相应的选择函数left-branch和right-branch,它们分别返回活动体的两个分支。还有branch-length和branch-structure,它们返回一个分支上的成分。
b)用你的选择函数定义过程total-weight,它返回一个活动体的总重量。
c)一个活动体称为是平衡的,如果其左分支的力矩等于其右分支的力矩(也就是说,如果其左杆的长度乘以吊在杆上的重量,等于这个活动体右边的同样乘积),而且在其每个分支上吊着的子活动体也都平衡。请设计一个过程,它能检查一个二叉活动体是否平衡。
d)假定我们改变活动体的表示,采用下面构造方式:
(define (make-mobile left right)
(cons left right))
(define (make-branch length structure)
(cons length structure))
你需要对自己的程序做多少修改,才能将它改为使用这种新表示?
a)
(define (compose f g) (lambda (x) (f (g x))))
(define left-branch car)
(define right-branch (compose car cdr))
(define branch-length car)
(define branch-structure (compose car cdr))
(define lb (make-branch 1 2))
(define rb (make-branch 2 4))
lb
rb
(define m (make-mobile lb rb))
m
(left-branch m)
(right-branch m)
b)
(define (total-weight m)
(define (total-weight-of-mobile m)
(define lb (left-branch m))
(define rb (right-branch m))
(define blb (branch-structure lb))
(define brb (branch-structure rb))
(+
(total-weight blb)
(total-weight brb)
)
)
(if (pair? m) (total-weight-of-mobile m) m)
)
(= (total-weight m) 6)
c)
(define (balance? m)
(define lb (left-branch m))
(define rb (right-branch m))
(define blb (branch-structure lb))
(define brb (branch-structure rb))
(and
(if (pair? blb) (balance? blb) #t)
(if (pair? brb) (balance? brb) #t)
(=
(* (branch-length lb) (total-weight blb))
(* (branch-length rb) (total-weight brb))
)
)
)
(balance? m)
d) 只需要修改一个选择函数,后面的高层函数完全不用修改!选择函数很好的完成了抽象屏障的作用
a) 改动: 可以省去 compose,直接调用 cdr
(define (make-mobile left right)
(cons left right))
(define (make-branch length structure)
(cons length structure))
(define left-branch car)
(define right-branch cdr)
(define branch-length car)
(define branch-structure cdr)
(define lb (make-branch 1 2))
(define rb (make-branch 2 4))
lb
rb
(define m (make-mobile lb rb))
m
(left-branch m)
(right-branch m)
b) 完全不用改
(define (total-weight-2 m)
(define (total-weight-of-mobile m)
(define lb (left-branch m))
(define rb (right-branch m))
(define blb (branch-structure lb))
(define brb (branch-structure rb))
(+
(total-weight blb)
(total-weight brb)
)
)
(if (pair? m) (total-weight-of-mobile m) m)
)
(= (total-weight-2 m) 6)
c) 完全不用改!
(define (balance-2? m)
(define lb (left-branch m))
(define rb (right-branch m))
(define blb (branch-structure lb))
(define brb (branch-structure rb))
(and
(if (pair? blb) (balance? blb) #t)
(if (pair? brb) (balance? brb) #t)
(=
(* (branch-length lb) (total-weight blb))
(* (branch-length rb) (total-weight brb))
)
)
)
(balance-2? m)