SICP 习题 (2.29) 解题总结:二叉活动体
2015-09-27 14:31
197 查看
SICP 习题 2.29题目很长,实现起来有点繁琐,不过题目不难,花点时间还是容易完成的。
题目引入了一个概念叫二叉活动体,这种东西有一个左分支,有一个右分支,每个分支包括一个长度和一个悬挂物,悬挂物可以是一个数,也可以是另一个二叉活动体。
题中给出了二叉活动体的实现代码:
也给出了分支的实现代码:
题目要求我们写出left-branch和right-branch的过程,用于返回左分支或者是右分支。这个比较简单,因为二叉活动体的实现代码中左分支和右分支是通过list过程组合起来的,将他们取出来的过程就分别是car和cadr,代码如下:
题目还要求我们实现branch-length和branch-structure过程,用于返回分支的长度和悬挂物。同样,实现的时候还是通过car和cadr分别取得,代码如下:
此外,题目还要求我们实现过程total-weight,用于获得一个二叉活动体的总重量。这个实现起来麻烦一点点,需要遍历整棵树,然后统计所有总量,代码如下:
接着,题目还要求我们实现一个balance?过程用于检查一个二叉活动体是否是平衡的,平衡的定义书中有说到,就是左分支重量乘以长度等于右分支重量乘以长度,而且所有子树都满足这样的条件。
借助以上实现的方法,检查一个二叉活动体是否平衡可以通过不断递归,不断判断每一个二叉分叉点来实现,代码如下:
最后,题目问我们如果活动体的实现过程中不是使用list过程,而是使用cons过程,我们的程序是否需要很大量的修改。因为我们使用接口封装了不同的获取函数,所以我们的代码不需要大量的修改,只需要改一下那些获取函数就可以了,比如right-branch过程中的cadr修改成cdr就好了:
题目引入了一个概念叫二叉活动体,这种东西有一个左分支,有一个右分支,每个分支包括一个长度和一个悬挂物,悬挂物可以是一个数,也可以是另一个二叉活动体。
题中给出了二叉活动体的实现代码:
(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))
相关文章推荐
- 选择问题——算法导论(10)
- [LeetCode][Java]Peeking Iterator
- SICP 习题 (2.28)解题总结:树状列表的遍历
- Xcode中如何更改Bundle identifier
- JDBC数据库连接的简单应用
- SICP 习题 (2.27)解题总结:树状列表的遍历
- 怎么彻底卸载Win10升级助手GWX文件?
- oracle之简null空值问题,用nvl(a,b)函数解决
- linuxC语言socket广播通信
- Google Java编程风格指南 - 转载及自己的标注
- WIN7用键盘控制鼠标
- JavaMe开发自适应滚动显示
- Android Material Design Snackbar Example
- JAVA基础学习(十七)--集合四 工具类Collections
- Construct Binary Tree from Inorder and Postorder Traversal
- JAVA基础学习day17--集合工具类-Collections
- 黑马程序员---java基础---面向对象中的构造方法及static关键字,变量的问题
- CoreData 实体之间的关系
- 总结学生选课Dao类相应代码,对应数据库表的内容进行修改
- 找回linux丢失的磁盘空间