抽象数据类型
抽象数据类型是描述数据结构的一种理论工具。在介绍抽象数据类型之前我们先介绍一下数据类型的基本概念。数据类型(data type)是一组性质相同的数据元素的集合以及加在这个集合上的一组操作。例如Java 语言中就有许多不同的数据类型,包括数值型的数据类型、字符串、布尔型等数据类型。以Java 中的int 型为例,int 型的数据元素的集合是[-2147483648,2147483647]间的整数,定义在其上的操作有加、减、乘、除四则运算,还有模运算等。定义数据类型的作用一个是隐藏计算机硬件及其特性和差别,使硬件对于用户而言是透明的,即用户可以不关心数据类型是怎么实现的而可以使用它。定义数据类型的另一个作用是,用户能够使用数据类型定义的操作,方便的实现问题的求解。例如,用户可以使用Java定义在int 型的加法操作完成两个整数的加法运算,而不用关心两个整数的加法在计算机中到底是如何实现的。这样不但加快了用户解决问题的速度,也使得用户可以在更高的层面上考虑问题。与机器语言、汇编语言相比,高级语言的出现大大地简便了程序设计。但是要将解答问题的步骤从非形式的自然语言表达到形式化的高级语言表达,仍然是一个复杂的过程,仍然要做很多繁杂琐碎的事情,因而仍然需要抽象。对于一个明确的问题,要解答这个问题,总是先选用该问题的一个数据模型。接着,弄清该问题所选用的数据模型在已知条件下的初始状态和要求的结果状态,以及隐含着的两个状态之间的关系。然后探索从数据模型的已知初始状态出发到达要求的结果状态所必需的运算步骤。我们在探索运算步骤时,首先应该考虑顶层的运算步骤,然后再考虑底层的运算步骤。所谓顶层的运算步骤是指定义在数据模型级上的运算步骤,或叫宏观运算。它们组成解答问题步骤的主干部分。其中涉及的数据是数据模型中的一个变量,暂时不关心它的数据结构;涉及的运算以数据模型中的数据变量作为运算对象,或作为运算结果,或二者兼而为之,简称为定义在数据模型上的运算。由于暂时不关心变量的数据结构,这些运算都带有抽象性质,不含运算的细节。所谓底层的运算步骤是指顶层抽象的运算的具体实现。它们依赖于数据模型的结构,依赖于数据模型结构的具体表示。因此,底层的运算步骤包括两部分:一是数据模型的具体表示;二是定义在该数据模型上的运算的具体实现。我们可以把它们理解为微观运算。于是,底层运算是顶层运算的细化,底层运算为顶层运算服务。为了将顶层算法与底层算法隔开,使二者在设计时不会互相牵制、互相影响,必须对二者的接口进行一次抽象。让底层只通过这个接口为顶层服务,顶层也只通过这个接口调用底层的运算。这个接口就是抽象数据类型。抽象数据类型(abstract data type, 简称ADT)由一种数据模型和在该数据模型上的一组操作组成。抽象数据类型包括定义和实现两个方面,其中定义是独立于实现的。抽象数据类型的定义仅取决于它的逻辑特性,而与其在计算机内部的实现无关,即无论它的内部结构如何变化,只要它的逻辑特性不变,都不会影响到它的使用。其内部的变化(抽象数据类型实现的变化)只是可能会对外部在使用它解决问题时的效率上产生影响,因此我们的一个重要任务就是如何简单、高效地实现抽象数据类型。很明显,对于不同的运算组,为使组中所有运算的效率都尽可能地高,其相应的数据模型具体表示的选择将是不同的。在这个意义下,数据模型的具体表示又依赖于数据模型上定义的那些运算。特别是,当不同运算的效率互相制约时,还必须事先将所有的运算的相应使用频度排序,让所选择的数据模型的具体表示优先保证使用频度较高的运算有较高的效率。我们应该看到,抽象数据类型的概念并不是全新的概念。抽象数据类型和数据类型在实质上是一个概念,只不过是对数据类型的进一步抽象,不仅限于各种不同的计算机处理器中已经实现的数据类型,还包括为解决更为复杂的问题而由用户自定义的复杂数据类型。例如高级语言都有的“整数”类型就是一种抽象数据类型,只不过高级语言中的整型引进实现了,并且实现的细节可能不同而已。我们没有意识到抽象数据类型的概念已经孕育在基本数据类型的概念之中,是因为我们已经习惯于在程序设计中使用基本数据类型和相关的运算,没有进一步深究而已。抽象数据类型一方面使得使用它的人可以只关心它的逻辑特征,不需要了解它的实现方式。另一方面可以使我们更容易描述现实世界,使得我们可以在更高的层面上来考虑问题。例如可以使用树来描述行政区划,使用图来描述通信网络。根据抽象数据类型的概念,对抽象数据类型进行定义就是约定抽象数据类型的名字,同时,约定在该类型上定义的一组运算的各个运算的名字,明确各个运算分别要 有多少个参数,这些参数的含义和顺序,以及运算的功能。一旦定义清楚,人们在使用时就可以像引用基本数据类型那样,十分简便地引用抽象数据类型;同时,抽象数据类型的实现就有了设计的依据和目标。抽象数据类型的使用和实现都与抽象数据类型的定义打交道,这样使用与实现没有直接的联系。因此,只要严格按照定义,抽象数据类型的使用和实现就可以互相独立,互不影响,实现对它们的隔离,达到抽象的目的。为此抽象数据类型可以使用一个三元组来表示:ADT = (D, S, P)其中D 是数据对象,S 是D 上的关系集,P 是加在D 上的一组操作。在定义抽象数据类型时,我们使用以下格式:ADT 抽象数据类型名{ 数据对象:<数据对象的定义>数据关系:<数据关系的定义>基本操作:<基本操作的定义>}更多精彩内容请关注:
关注超人学院微信二维码:
关注超人学院java免费学习交流群: