关于ADT的一些简单解释及理解

        笔者写这篇文章的初衷是帮助刚刚接触软件构造课程的小白通俗易懂地解释关于ADT方面地知识(才不是为了作业呢)。虽然说上课老师讲的很不错,课件ppt也都提供了,本来也不需要我在这里过多的解释什么,但是ppt上大多是大段的英文,即便有少量中文来标记重要的知识点,但是如果不阅读那些英文的话是没有办法很好的理解的。笔者就当抛砖引玉,简单谈谈自己关于抽象数据类型(ADT)的理解。

        最早接触到ADT概念的应该是大二上的数据结构课程上,当时只学了个概念,但是并没有很好的理解其具体意思。

一.ADT简介与特征

        抽象数据类型Abstract Data Type,简称ADT):是计算机科学中具有类似行为的特定类别的数据结构的数学模型;或者具有类似语义的一种或多种程序设计语言的数据类型。抽象数据类型是间接定义的,通过其上的可执行的操作以及这些操作的效果的数学约束(与可能的代价)。

        定义显然是不直观的。毕竟人家叫抽象数据类型嘛,肯定和数据类型有一定的关联。我们一般用的int啊,double啊这些,称为数据类型,有什么作用呢?显然是为了表示数据。short表示的范围小,int表示的范围大;int表示整数,double可以表示浮点数······可以发现,数据类型强调数据的“具体表示”。但是,ADT既有“抽象”二字,与之就有不同之处。ADT更加强调作用在数据上的“操作集合”,我们并不关心数据在ADT中是如何存储的,而ADT数据如何操作则是我们的重点。例如我们常常自己定义了一个myString来进行String操作。如果把myString看成一个抽象数据类型,那么我们完全不关心String是char数组存储,还是链表存储or其他。我们只关心操作,如求字符串长度啊,打印字符串啊,取子串等。ADT是由操作定义的,与其内部如何实现无关!

二.ADT的分类与组成

1.ADT的分类

        我们通常将ADT分为不可改变的(immutable)和可改变的(mutable)。在不可改变的情况下,当我们需要改变值的时候必须建立一个新的对象;而可改变的情况则直接改变该对象的值。

2.ADT的组成

        ADT的组成,如果用形式化的定义去描述,理解起来可能会比较困难,笔者希望通过生动的比喻来通俗的阐述以下这些名词,如果有粗糙之处还请见谅。我们建立一个“一桶水彩笔”的ADT。

        a.构造器(creator):我们声明了一个具体的一桶水彩笔 ,可以理解为笔的初始化,他不再是一个概念了,而是一个真实的存在了,无中生有。

        b.生产器(producer):生产器针对已经存在的实物。例如我这里有两桶笔,我可以通过生产器将他们合并,成为一桶笔。注意我们的ADT是以“一桶水彩笔”作为概念的,因此这里合成的“一同水彩笔”其实也是新的对象,但是是从已经真实存在的“两桶水彩笔”出发的。

        c.观察器(observer):观察已经存在的实物。例如一桶水彩笔里的颜色,数量等等。

        d.变值器(mutator):对已经存在的实物的改变,例如改变一桶水彩笔里笔的数量,颜色等等。

3.一些笔者曾陷入的误区,提醒

        a.在PPT中曾经说到int是不可改变的,但是笔者一直不明白。因为数字我们知道是可以相加减的,怎么能说他是不可改变的呢。但其实,这个不可改变是针对对象而言的,对于1这个数来说,他既是个数,也是一个对象,1永远是1,是不会改变的。而像list表来说,一个表的元素可以添加可以删除,改变了这个对象,因此称为是可改变的。

        b.不可改变的ADT不会含有变值器。这个规则其实与a有异曲同工之妙。因为是不可改变的,因此不可能存在变值器能够改变他的值。通常来说变值器的返回值是void类型的,但也有少数会存在返回值。

三.表示独立性(representation Independence)

        表示独立性: 用户在使用 ADT 时无需考虑其内部如何实现, ADT 内部表示的变化不应影响外部规则和客户端。

        简单来说就是数据类型的封装性。就像我们在定义int类型的数据时只要简单的声明就可以了,并不用深究深层的原理是什么;在使用抽象数据类型时用户也不需要知道内部是如何完成的,只需要声明就可以了,而且我们知道ADT针对操作集合,因此在使用操作时也只需要满足外部的要求就可以了,并不需要了解内部构造。

 四.关于RI和AF(Rep Invariant and Abstraction Function)

        不得不说,,虽然身为中国人笔者很自豪,但很多时候不懂英语确实对学习有些影响(笔者英语太差了呜呜)。其实一些很简单的概念常常会因为英文的复杂而感到头大,呃呃,回归正题。

        首先,因为上述的表示独立性,即用户使用ADT时无需考虑内部的实现,因此对客户的数据的表示和对内部的数据的存储可能会有不同。我们把面向客户的数据空间称为抽象空间(A),而对内部的存储以及处理的数据空间称为表示空间(R)。对于客户来说,只要程序能够输出正确的值就可以了,但是对于程序员来说,内部表示空间的存储才是着手的地方。

        AF(Abstraction Function)实际上是内部空间(R)到抽象空间(A)的一个映射。这个映射在一定程度上可以说是程序的目的,也就是我们设计程序的原因。如下图是一个输入字符串输出字符串里字符的集合。                                                                                                                           AF : R->A  

                

         由A和R的定义我们能够简单分析出,R中的每一个元素未必能够映射到A中,但是A中的元素一定是R中的元素映射过去的,这个映射一定是一个满射,但未必是单射,双射。那么,怎么判断R中的元素是有效的呢(能够映射到A中)?

        由上述这个问题,RI应运而生。RI就是用来判断R空间中的数据是否合法的,这一步也是在ADT的内部完成,不需要透露给客户端。如下图,RI就将具有重复字符的字符串给不合法化了。

RI:  R->boolean

               

     

         因此,在编写具有普适性的ADT时,在代码内部一定要把RI解释的简单又清楚,这样才方便后续的程序员了解规则。

五.结语

        至此,笔者将ADT的大致模样简单的描述了一下。关于ADT的设计原则,ADT中的不变量等笔者觉得学习起来没有上述知识那么复杂,因此并没有过多介绍,希望各位大佬不吝赐教,各位小白读了笔者这篇文章能够有所收获,也希望笔者的小文让你们读起来没有那么晦涩,幸会。

   

        

        

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值