《计算机程序的构造与解释》(八)
来源:互联网 发布:mysql jdbc maven 编辑:程序博客网 时间:2024/05/16 16:01
在《SICP》第二章开始介绍数据抽象时,抽象出有理数的构造和选择函数,然后在这个接口上再定义有理数的基本操作过程,实现了有理数的具体表示和使用的分离。然后又介绍了序对和表结构,以及把表和树作为操作单元的一些过程,有map、tree-map、append、reverse等等。
现在要求一棵树的所有奇数叶子的平方和,按照之前的方法是遍历树,然后判断每个元素是否奇数,如果是则累加起来。
(define (sum-odd-squares tree) (cond ((null? tree) 0) ((not (pair? tree)) (if (odd? tree) (square tree) 0)) (else (+ (sum-odd-squares (car tree)) (sum-odd-squares (cdr tree))))))(sum-odd-squares '(1 (2 3) (4 5 6)));->35从上面的代码可以看出,在判断tree是否为原子时(not paire?),对树的元素进行了过滤,如果是odd?,那么就求平方;如果tree是一个表结构,那么递归求这个表结构的car和cdr两部分。实际上,如果改变策略,进行下面的抽象会看出一类数据抽象模式。
上面的例子需要:
- 枚举出一棵树的叶子节点;
- 判断是否为奇数,过滤掉非奇数的节点数值;
- 对过滤后得到的所有数值进行平方运算;
- 用+累积求平方的结果,从0开始。
可以把需要处理的数据当作数据流看待,就得到下面的框图:
在上面的代码中,这些步骤是相互混合的,没有清晰的层次。如果能设计出像信号处理流程那样清晰的结构,将极大提高代码的清晰性、可读性。
那么必须要考虑的第一个问题是,如何在各个处理步骤间表示数据?这个数据结构能方便的连接各个处理过程,能在它们之间方便的传递,并且有助于每个步骤的处理过程简化,从而逐步接近最终的目标。这个数据结构就是——表!如前面讲的map过程,(map square ls)计算出ls每个元素的平方,然后组成一个表返回。还可以定义filer过程,(filter predicate sequence)将表sequence中满足predicate情形的元素留下,而不满足的过滤掉,最后返回的也是表。还有一个关键的步骤,是枚举过程,即从原始数据结构中以表的形式枚举出所有待处理的元素,然后交由后续过程处理。根据上面所列的步骤,逐步定义enumerate、filter、map和accumulate过程,并且重写sum-odd-squares。
> (define (enumerate-tree tree) (cond ((null? tree) null) ((not (pair? tree)) (list tree)) (else (append (enumerate-tree (car tree)) (enumerate-tree (cdr tree))))))> (enumerate-tree '(a b c ( d (e f))))'(a b c d e f)> (define (filter predicate sequence) (cond ((null? sequence) null) ((predicate (car sequence)) (cons (car sequence) (filter predicate (cdr sequence)))) (else (filter predicate (cdr sequence))))) > (filter odd? '(1 2 3 4))'(1 3)> (filter odd? (enumerate-tree '(1 2 ( 3 4 5) ( 43 5 6(45 (567 897))))))'(1 3 5 43 5 45 567 897)> (define (accumulate op initial sequence) (if (null? sequence) initial (op (car sequence) (accumulate op initial (cdr sequence)))))> (accumulate + 0 '(1 2 3 4))10> (accumulate * 1 '( 1 2 3 4))24> (define (map proc ls) (cond ((null? ls) null) (else (cons (proc (car ls)) (map proc (cdr ls)))))) > (map sqr '( 1 2 3 5))'(1 4 9 25)上面定义了几个需要用到的抽象过程,它们可以根据计算目的重新组合,例如sum-odd-squares过程重写后如下:
> (define (newoddsqr sequence) (accumulate + 0 (map sqr (filter odd? (enumerate-tree sequence)))))> (newoddsqr '( 2 3 4( 4 ( 5 6 7))))83这样的高度的模块化设计,使得程序维护变得非常简单。如果要实现求偶数的平方和,那么只要换一个过滤条件就可以了。把odd?改成even?,就可以定义newevensqr过程了。只要改变map的过程参数,就可以对元素进行其他运算,如求立方和等等。
0 0
- 《计算机程序的构造与解释》(八)
- 计算机程序的构造与解释(SICP)
- 计算机程序的解释与构造1
- 计算机程序的构造与解释
- 《计算机程序的构造与解释》(一)
- 《计算机程序的构造与解释》(二)
- 《计算机程序的构造与解释》(三)
- 《计算机程序的构造与解释》(四)
- 《计算机程序的构造与解释》(五)
- 《计算机程序的构造与解释》(六)
- 《计算机程序的构造与解释》(七)
- 《计算机程序的构造与解释》(九)
- 《计算机程序的构造与解释》(十)
- 《计算机程序的构造与解释》(十一)
- 《计算机程序的构造与解释》(十二)
- 《计算机程序的构造与解释》(十三)
- 《计算机程序的构造与解释》(十四)
- 《计算机程序的构造与解释》(十五)
- 批处理dos下获取当前路径命令
- SIM卡文件表
- 探讨网站推广方式之论坛推广 [
- 便利店O2O大跃进 顺丰嘿店未过“烧钱期”
- [Oracle] 分析函数(2)- 开窗(WINDOWING)
- 《计算机程序的构造与解释》(八)
- javascript控制在光标位置插入文字
- QT_PC学习_多媒体入门_简单场合应用
- 开发Python用什么工具好?
- Android Studio 快捷键
- Objective-C编程之道:iOS设计模式解析(一)工厂模式
- AWR的基本知识
- 两个正续排列的数组,组合成一个正续排列的数组
- 把十进制数(long型)分别为二进制和十六进制形式输出,不能使用printf