一. 抽象数据类型(ADT)的概念
一个ADT是一个仅由保存的数据类型和可能在这个数据类型上进行的操作定义的。开发者们只能通过ADT的操作方法来访问ADT的属性,而且他们不会知道这个数据类型内部各种操作是如何实现的。 在Java中,我们常常使用一个接口来给出一个操作集合而不需要透露这些操作实现的细节。 ADT提供了一个将对象公共接口中的操作和其具体的实现分开的强有力的工具。这使得一个ADT的实现可以不断变化和演化同时保持其公共接口不变。
可以说,数据得抽象是用抽象数据类型来实现的,ADT是这个集合和定义在这集合上的一组数据操作,它不包括计算机数据存储:隐藏了数据存储结构并且不涉及实现结构的数据类型。
java中抽象数据类型的描述:1.抽象类(abstraction class),抽象类型的实现用继承该抽象类的子类表示, 2.接口(interface) ,抽象类型的实现用实现该接口的类表示。
二. ADT的意义
ADT是作为支持模块化编程的一种有效机制。模块化编程是现代大型软件系统的一种组织方法。ADT提供了灵活的修改,ADT接口明确定义了程序访问的方法。
抽象数据类型包括定义和实现两个方面,其中定义是独立于实现的。抽象数据类型的定
义仅取决于它的逻辑特性,而与其在计算机内部的实现无关,即无论它的内部结构如何变化,
只要它的逻辑特性不变,都不会影响到它的使用。其内部的变化(抽象数据类型实现的变化)
只是可能会对外部在使用它解决问题时的效率上产生影响,因此我们的一个重要任务就是如
何简单、高效地实现抽象数据类型。很明显,对于不同的运算组,为使组中所有运算的效率
都尽可能地高,其相应的数据模型具体表示的选择将是不同的。在这个意义下,数据模型的
具体表示又依赖于数据模型上定义的那些运算。特别是,当不同运算的效率互相制约时,还
必须事先将所有的运算的相应使用频度排序,让所选择的数据模型的具体表示优先保证使用
频度较高的运算有较高的效率。
三. ADT设计规范
数据类型可以使用一个三元组来表示:
ADT = (D, S, P)
其中D 是数据对象,S 是D 上的关系集,P 是加在D 上的一组操作。
在定义抽象数据类型时,我们使用以下格式:
ADT 抽象数据类型名{
数据对象:<数据对象的定义>
数据关系:<数据关系的定义>
基本操作:<基本操作的定义>
}
四. 范例
1.点的类实现
- public class Point{
- private double x,y;
- Point(){
- x = Math.random();
- y = Math.random();
- }
- Point(double x, double y){
- this.x = x;
- this.y = y;
- }
- double x(){
- return x;
- }
- double y(){
- return y;
- }
- double r(){
- return Math.sqrt(x * x + y * y);
- }
- double theta(){
- return Math.atan2(y , x);
- }
- double distance(Point p){
- double dx = x - p.x;
- double dy = y - p.y;
- return Math.sqrt(dx * dx + dy * dy);
- }
- public String toString(){
- return "(" + x + " , " + y + ")";
- }
- }
2.复数运算
- interface IComplex // 取实部
- {
- public double getReal(); //修改实部
- public void setReal(double real); //取虚部
- public double getimag(); //修改虚部
- public void setimag(double imag); //两个复数的求和
- public void add(IComplex Z);
- }
- public class Complex implements IComplex {
- private double real; //实部
- private double imag; //虚部
- public Complex(double real,double imag) { //构造一个实数
- this.real=real;
- this.imag=imag;
- }
- public double getReal() { //取实部 return real;
- }
- public void setReal(double real) { //修改实部 this.real=real;
- }
- public double getimag() {
- return imag;
- }
- public void setimag(double imag) {
- this.imag=imag;
- }
- public void add(IComplex Z) {
- if(Z!=null) {
- real+=Z.getReal();
- imag+=Z.getimag();
- }
- }
- }
五. 设计ADT的规则总结
1.设计简洁,操作一致
It’s better to have a few, simple operations that can be combined in
powerful ways, rather than lots of complex operations.
– Each operation should have a well-defined purpose, and should have a
coherent behavior rather than a panoply of special cases.
– We probably shouldn’t add a sum operation to List , for example. It might
help clients who work with lists of integers, but what about lists of
strings? Or nested lists? All these special cases would make sum a hard
operation to understand and use.
设计一组简单操作,通过简单操作的组合实现复杂的操作。操作的行为应该
是内聚的。
2.要足以支持client 对数据所做的所有操作需要,且用操作满足client
判断方法:对象每个需要被访问到的属性是否都能够被访问到,例如list这个ADT:
①必须要有get()操作,没有get()操作就无法获取list的内部数据。
②用遍历方式获取list的size –太复杂 vs 提供size()操作,方便client使用。
3.要么抽象、要么具体,要么针对抽象设计,要么针对具体应用的设计,不要混合
(1)The type may be generic: a list or a set, or a graph, for example.
数据类型可以是概括性的,例如:表,集合,或者图。
(2)Or it may be domain-specific: a street map, an employee database,
a phone book, etc.
或者数据类型是专注于某领域的,例如:一个街道地图,一个员工数据库,一个电话簿……
(3)But it should not mix generic and domain-specific features.
一定不能将抽象概括的类型和专注于某领域的类型搞混。
六.抽象数据类型在Java中的实现归纳