《构造数据抽象》PPT课件.ppt
《《构造数据抽象》PPT课件.ppt》由会员分享,可在线阅读,更多相关《《构造数据抽象》PPT课件.ppt(84页珍藏版)》请在三一办公上搜索。
1、构造数据抽象,到目前为止,我们操作的都是简单的数值数据,而对我们希望处理的许多问题而言,这种简单数据还不够。许多程序在设计时就是为了模拟复杂的对象,因此他们就常常需要构造起一些计算对象。与我们在前面所做的事情一样,我们将重点转到各种程序设计语言的另一关键方面:讨论他们所提供的,将数据对象组合起来,形成复合数据的方式,并进一步去考查更复杂的数据。同样的我们还将要看到,与过程抽象相对应的,另一种强有力的设计方法学数据抽象,构造数据抽象,数据抽象是一种方法学,它使我们能够将一个复合数据对象的使用,与该数据对象怎样由更基本的数据对象构造起来的细节隔离开来。其基本思想,就是设法构造出一些使用复合对象的程
2、序,使它们就像是在“抽象数据”上操作一样。也就是说,我们的程序中使用数据的方式应该是这样的:除了完成当前工作所必要的东西之外,它们不对所用数据做任何多余的假设。与此同时,一种“具体”数据表示的定义,也应该与程序中使用数据的方式无关。我们利用一组称为选择函数和构造函数的过程作为这两个部分之间的界面。,构造数据抽象,实例研究:有理数的算术运算我们希望能做有理数的加减乘除,比较两个有理数是否相等。我们假定已经有了一种从分子和分母构造有理数的方法。进一步假定,如果有了一个有理数,我们有一种方法取得它的分子和分母。现在再假定有关的构造函数和选择函数都可以做为过程使用:(make-rat)返回一个有理数,
3、其分子是整数,分母是整数(numer)返回有理数的分子(denom)返回有理数的分母这里使用一种称为按愿望思维的策略。现在我们还没有说有理数将如何表示,也没有说过程make-rat,numer和denom应如何实现。利用这三个过程我们就可以实现有理数的运算了,构造数据抽象,有理数运算过程的实现:加法过程:(define(add-rat x y)(make-rat(+(*(numer x)(denom y)(*(numer y)(denom x)(*(denom x)(denom y)减法过程:(define(sub-rat x y)(make-rat(-(*(numer x)(denom y)
4、(*(numer y)(denom x)(*(denom x)(denom y),构造数据抽象,乘法过程:(define(mul-rat x y)(make-rat(*(numer x)(numer y)(*(denom x)(denom y)除法过程:(define(div-rat x y)(make-rat(*(numer x)(denom y)(*(denom x)(numer y)相等判断过程:(define(equal-rat?x y)(=(*(numer x)(denom y)(*(numer y)(denom x),构造数据抽象,有理数的表示:我们已经定义了在过程make-rat
5、,numer和denom基础上的各种有理数的运算过程,而这些基础还没有定义。现在需要某种方式,将一个分子和一个分母粘接起来,构成一个有理数。在实现有理数之前我们先来看看我们所用的语言提供的一种称为序对的复合数据。序对为完成这里的有理数系统提供了一种自然的方式,我们可以将有理数简单的表示为两个整数(分子和分母)的序对。,构造数据抽象,序对:同样我们只关心序对选择函数和构造函数的形式,而实际过程已由解释器实现了(cons),过程cons取两个参数,返回一个包含这两个参数作为其成分的复合数据对象(car),其序对中的第一个参数(cdr),其序对中的第二个参数注意一个序对也是一个数据对象,可以像基本数
6、据对象一样给它一个名字且操作它。还可用cons构造其元素本身就是序对的序对,例如:(define x(cons 1 2)(define y(cons 3 4)(define z(cons x y)(car(car z)1(car(cdr z)2,构造数据抽象,基于序对的有理数的表示:(define(make-rat n d)(cons n d)(define(numer x)(car x)(define(denom x)(cdr x)为了显示计算结果我们再定义一个打印函数,它以一个有理数作为输入并把它打印出来。(define(print-rat x)(newline)(display(nume
7、r x)(display/)(display(denom x)这里我们用到了两个scheme的基本内置过程display和newline。Display为打印数据的基本过程,newline为随后的打印开始一个新行。,构造数据抽象,(define one-half(make-rat 1 2)(print-rat one-half)(define one-third(make-rat 1 3)(print-rat(add-rat one-half one-third)(print-rat(mul-rat one-half one-third)(print-rat(add-rat one-third
8、 one-third)看看上面的过程都会打印出什么?从打印结果你们发现了什么问题?能否改进?,构造数据抽象,抽象屏障:在继续讨论之前,让我们首先回顾一下有理数系统的结构:问题域中的有理数 作为分子和分母的有理数 作为序对的有理数 当然序对也需要实现,使用有理数的程序,add-rat sub-rat,cons car cdr,make-rat number denom,构造数据抽象,其中的水平线表示抽象屏障,它隔离了系统的不同层次,它把使用数据的程序和实现数据的程序分开,使得一层中的过程的实现与其他层的过程的实现完全无关。从作用上看,每一层中的过程构成了所定义的抽象屏障的界面,联系起系统中的不同
9、层次。这种简单思想有许多优点:这种方法使程序很容易维护和修改有助于程序的设计,使我们能保留考虑不同实现方式的灵活性,使我们能推迟决策的时间,而又不会阻碍系统其他部分的工作进展。你能给出几种不同的有理数表示?它们各有什么优缺点?,构造数据抽象,数据意味着什么前面我们看到在抽象层面上数据可以描述为一组选择函数和构造函数,但是说它就是“由给定的选择函数和构造函数所实现的东西”还是不够的。显然,并不是任意的三个过程都适合作为有理数实现的基础。这里我们还需要保证,如果从整数n和d构造出一个有理数x,那么抽取出的x的number和denom并将他们相除,得到的结果应该与n除以d相同。也就是说这些基本过程的
10、选择是带有约束的。一般而言,我们总可以将数据定义为一组适当的选择函数和构造函数,以及为使这些过程成为一套合法表示,它们就必须满足的一组特定条件。从上面我们可以得出一个结论:数据其实就是一组定义良好的过程。确实,考虑序对,我们完全可以不用任何数据结构,只用过程实现它。,构造数据抽象,序对的过程实现:(define(cons x y)(define(dispatch m)(cond(=m 0)x)(=m 1)y)(else(error Argument not 0 or 1-CONS m)dispatch)(define(car z)(z 0)(define(cdr z)(z 1)这确实与我们有关
11、数据应该是什么的直观认识大相径庭。这一实例说明可以将过程作为对象去操作,因此就自动地为我们提供了一种表示复合数据的能力。这些东西现在看起来好像只是很好玩,但实际上,数据的过程性表示将在我们的程序设计宝库里扮演一种核心角色。有关的程序设计风格通常称为消息传递。,层次性数据和闭包性质,前面已经看到,序对为我们提供了一种用于构造复合数据的基本“粘接剂”,我们可以建立元素本身也是序对的序对,序对的这种能力称为cons的闭包性质。一般说,某种数据对象的操作满足闭包性质,就是说,通过它组合起数据对象得到的结果本身还可以通过同样的操作再进行组合。闭包性质是任何一种组合功能的威力的关键要素,它使我们能够建立起
12、层次性的结构。,层次性数据和闭包性质,层次性结构的表示:图中展示的是序对的标准表示,其中的序对是通过(cons 1 2)形成的。这种称为盒子和指针表示方式中,每个对象表示为一个指向盒子的指针。与基本对象相对应的盒子包含着该对象的表示。复合层次结构的表示:,层次性数据和闭包性质,序列的表示:我们可以用序对构造一种有用的数据结构序列,它是一批数据对象的一种有序汇集。采用序对表示序列有很多种方式,在这里我们采用一种标准的方式来表示。下面是对序列1,2,3,4的表示:(cons 1(cons 2(cons 3(cons 4 nil)通过嵌套的cons形成的这样一个序对的序列称为一个表,scheme为方
13、便表的构造,提供了一个基本操作list,如(list 1 2 3 4)。一般的:(list.)等价于:(cons(cons(cons.(cons nil).),层次性数据和闭包性质,序对的打印:(cons 1 2);(1.2)(cons(cons 1 2)(cons 3 4);(1.2)3.4)(cons 1(cons 2(cons 3 nil);(1 2 3),层次性数据和闭包性质,表的打印:(list 1 2 3 4);(1 2 3 4)(define one-through-four(list 1 2 3 4)one-through-four;:(1 2 3 4)(car one-thr
14、ough-four);:1(cdr one-through-four);:(2 3 4)(car(cdr one-through-four);:2(cons 10 one-through-four);:(10 1 2 3 4),层次性数据和闭包性质,表操作:利用序对将元素表示为表之后,我们就可以使用常规的程序设计技术,通过”向下cdr”表的方式完成对表的各种操作了。返回指定标号的元素操作:list-ref(define(list-ref items n)(if(=n 0)(car items)(list-ref(cdr items)(-n 1)(define squares(list 1 4
15、9 16 25);:(list-ref squares 3)16注意:这里我们习惯令表元素的编号从0开始。,层次性数据和闭包性质,返回表的长度操作:length(define(length items)(if(null?items)0(+1(length(cdr items)(define odds(list 1 3 5 7)(length odds)4这里我们需要用到scheme提供的一个基本操作null?,用于检查参数是不是空表。上面的过程是一个递归的过程,空表的length为0,任一表的length等于其cdr的length加1.给出迭代的length过程?,层次性数据和闭包性质,连接表
16、操作:append(define(append list1 list2)(if(null?list1)list2(cons(car list1)(append(cdr list1)list2)(append squares odds);:(1 4 9 16 25 1 3 5 7)(append odds squares);:(1 3 5 7 1 4 9 16 25)append也是一种递归方案,能否给出迭代形式?,层次性数据和闭包性质,对表的映射:例:对给定表的所有元素按给定因子做一次放缩(define(scale-list items factor)(if(null?items)nil(co
17、ns(*(car items)factor)(scale-list(cdr items)factor)(scale-list(list 1 2 3 4 5)10);:(10 20 30 40 50)这里我们想抽象出这一具有一般性的想法,将其中公共模式表述为一个高阶过程,这一高阶过程称为map,它有一个过程参数和一个表参数,返回将这一过程应用于表中各个元素得到的结果形成的表。,层次性数据和闭包性质,对表的映射过程:map(define(map proc items)(if(null?items)nil(cons(proc(car items)(map proc(cdr items)(map(la
18、mbda(x)(*x x)(list 1 2 3 4)(1 4 9 16)用map重新定义scale-list过程:(define(scale-list items factor)(map(lambda(x)(*x factor)items),层次性数据和闭包性质,层次性结构:(1 2)3 4)是通过(cons(list 1 2)(list 3 4)构造出来的,其结构如下:认识这种元素本身也是序列的序列的另一种方式,是把它们看作树。序列里的元素就是树的分支,而那些本身也是序列的元素就形成了树中的子树。如图:,层次性数据和闭包性质,树操作:统计叶子数目操作:count-leaves(define
19、(count-leaves x)(cond(null?x)0)(not(pair?x)1)(else(+(count-leaves(car x)(count-leaves(cdr x)为了实现这一过程,我们需要一个判断参数是否为序对的函数,scheme提供了基本过程pair?,层次性数据和闭包性质,对树的映射:(define(scale-tree tree factor)(cond(null?tree)nil)(not(pair?tree)(*tree factor)(else(cons(scale-tree(car tree)factor)(scale-tree(cdr tree)facto
20、r)(scale-tree(list 1(list 2(list 3 4)5)(list 6 7)10);:(10(20(30 40)50)(60 70)该过程以一个数值因子和一颗叶子为数值的树作为参数,返回一颗具有同样形状的树。,层次性数据和闭包性质,下面我们利用前面介绍表的map过程重写如下:(define(scale-tree tree factor)(map(lambda(sub-tree)(if(pair?sub-tree)(scale-tree sub-tree factor)(*sub-tree factor)tree)也已看到这里map过程的写法已经没有在用于处理表时那么自然了
21、,究其原因是因为map过程并不具备处理层次结构的能力,这样我们在使用是就必须把相关处理写到其参数proc的过程里面。自然地,我们希望能有一个能处理这种层次结构的map过程,当然其肯定也包含了处理表结构的能力,应为树结构是一种比表更抽象的结构。,层次性数据和闭包性质,重写前面的map过程如下:(define(map proc items)(cond(null?items)nil)(pair?items)(cons(map proc(car items)(map proc(cdr items)(else(proc items)请利用新定义的map过程重写scale-list和scale-tree,
22、层次性数据和闭包性质,序列作为一种约定的界面:下面这个例子以一棵树为参数,计算出那些值为奇数的叶子的平方:(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)该过程的大致处理步骤如下:枚举出一棵树的树叶;过滤他们,选出其中的奇数;对选出的每个数求平方;再用+累积起得到的结果,从0开始。,层次性数据和闭包性质,这种过程可以很自然地用流过一些级联的处理步骤
23、的信号的方式描述,其中的每个处理步骤实现程序方案中的一个部分,如图所示:我们从一个枚举器开始,它产生出由个给定的树的所有树叶组成“信号”。这一信号流过一个过滤器,所有不是奇数的数都被删除了。这样得到的信号又通过一个映射,这是一个“转换装置”,它将square过程应用于每个元素。这一映射的输出被馈入一个累积器,该装置用+将得到的所有元素组合起来,从0开始。,enumerate:tree leaves,filter:odd?,map:square,accumulate:+,0,层次性数据和闭包性质,序列操作:要组织好反映上面信号流的结构的程序,最关键的一点就是将注意力集中在处理过程中从一个步骤流向
24、下一个步骤的“信号”。这些信号应该有稳定而灵活的结构,基于其上的基本操作可以组织好这些处理过程。表在这里就是一个良好的选择。基于表结构我们可以很好的实现信号流图中的过程如下:前面的map过程可以用来实现信号流图中的映射步骤:过滤一个序列,就是选出其中满足某个给定谓词的元素,实现如下:(define(filter predicate sequence)(cond(null?sequence)nil)(predicate(car sequence)(cons(car sequence)(filter predicate(cdr sequence)(else(filter predicate(cdr
25、 sequence),层次性数据和闭包性质,累积工作可以实现如下:(define(accumulate op initial sequence)(if(null?sequence)initial(op(car sequence)(accumulate op initial(cdr sequence)剩下的就是枚举出需要处理的数据序列,对于上面的例子,需要枚举出一棵树的所有树叶,可实现如下:(define(enumerate-tree tree)(cond(null?tree)nil)(not(pair?tree)(list tree)(else(append(enumerate-tree(ca
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 构造数据抽象 构造 数据 抽象 PPT 课件

链接地址:https://www.31ppt.com/p-5531846.html