抽象数据类型(ADT)入门(一)
1、抽象数据类型(Abstract Data Types,ADT)和ADT的实现
抽象数据类型:一个数据元素集合以及在这些数据上的操作。
ADT的一个实现包括存储数据元素的存储结构以及实现基本操作的算法。
在这个数据抽象的思想中,数据类型的定义和它的实现是分开的,这在软件设计中是一个重要的概念。这使得只研究和使用它的结构而不用考虑它的实现细节成为可能。实际上,这通常使用在int、double、char和bool等预定义数据类型上的方法,使用这些数据类型的程序员在绝大部分时间里不需要担心这些数据类型是如何实现的。
2、C++的简单数据类型以及它们是如何实现的?
C++中的基本数据类型如int/char/double/float等被称为简单数据类型,这是因为这些数据类型的值都是原子性的,也就是说,它是由不可再分的一个单独的实体构成的。但是它们又可以被看成是抽象数据类型,因为这些数据类型描述了一系列的值并提供了在这些值上操作的实现,对它们中的每一个来说,都是使用存储器单元作为存储结构,而它们的基本操作则是由计算机系统的硬件或者软件实现的。
(1)、整型数据:
无符号整数:非负整数,有时也被称为基数或全数,其集合是{0,1,2,3,....}。在C++中,这个ADT是通过3种数据类型建模的:unsigned short int(unsigned short)、unsigned int(unsigned)、unsigned long int(unsigned long),这些类型的值在内存中存储为一个位串。它们的长度必须满足:
sizeof(unsigned short) ≦ sizeof(unsigned) ≦ sizeof(unsigned long)
注:sizeof是一个C++的运算符,返回一个类型所占的字节数。典型地,unsigned short类型的值用2个字节存储,unsigned类型的值用4个字节存储,而unsigned long类型的值用4或8个字节存储。
下面给出示例代码:
#include<iostream> using namespace std; int main() { cout<<"sizeof(unsigned short)="<<sizeof(unsigned short)<<endl; cout<<"sizeof(unsigned)="<<sizeof(unsigned)<<endl; cout<<"sizeof(unsigned long)="<<sizeof(unsigned long)<<endl; return 0; }结果如下图所示:
带符号整数:整数集合{....,-3,-2,-1,0,1,2,3,....}以及熟悉的一些算术运算也构成一种ADT。在C++中,这个ADT是通过3种数据类型建模的:short int(short)、int、long int(long)。典型地,short类型的值用2个字节存储,int类型的值用4个字节存储,而long类型的值用4或8个字节存储。
注:正数和负数的原码都是其本身,只需在首位加上符号位即可;正数的反码不变,负数的反码是除符号位之外全反;正数的补码不变,负数的补码是符号位不变,全反加1即可。它们之间的区别见下图:
(2)、实型数据:
实数值,也称为浮点值,在C++中是通过单精度类型float,双精度类型double和扩展精度类型long double来建模的。
其中,double是处理实数数据的默认数据类型;可以在一个实数常量的后面添加一个后缀F从而规定将这个实数常量当做float值处理;如果添加一个L后缀,则规定将这个实数常量当做long double值处理。
注:在一个实数数字的二进制表示被存储到存储器之前,通常都要将它转换为浮点形式。
注:实数值的存储会存在“舍入错误”,这种错误可以通过存储更多数量的位数来减少,但是不能够被完全消除。请理解理论上的数值和计算机能存储的值之间的区别!!!这也是一个ADT不能完全忠实于这个ADT的表示(数学上的)实数和在实数上的操作的一个例子。
(3)、字符数据:
在编程语言中主要使用两种字符集。ASCII(America Standard Code for Information Interchange,美国信息交换标准码)是最常用的,但是一些语言使用Unicode,例如Java。而在C++中,字符通常都是使用char类型来处理的,这种类型使用一个能存储在一个字节中的数字代码表示每个字符。而Unicode使用了2个字节编码。
C++提供了宽字符类型wchar_t来存储Unicode之类的大字符集中的字符。在C++中,字符值可以被当做整数值处理:
int(char_value)=char_value的整数代码
实际上,char类型的值可以和数字值一起组合到算术表达式中,此时将使用char型值的数字编码。
(4)、布尔数据:
在C++中布尔值和布尔运算是通过bool数据类型建模的。有两个布尔常量:false(0)和true(1)。
在输入和输出bool型值时,会自动进行这些数字值和布尔值之间的转换。
3、ADT的实现并不忠实于ADT的表示的例子
对所有有限多个数据元素的ADT来说,表示数据值集合上的限制都是固定的,因为用来存储这些元素的内存是有限的。
ADT的实现并不忠实于ADT的表示的例子:溢出。
下面给出两个例子作为证明。
//-- Program to demonstrate the effects of overflow #include <iostream> using namespace std; int main() { int number = 2; for (int i = 1; i <= 15; i++) { cout << number << endl; number *= 10; } }结果如下图:
//-- Program to demonstrate the effects of overflow #include <iostream> #include <climits> using namespace std; int main() { int number = INT_MAX - 3; for (int i = 1; i <= 7; i++) { cout << number << endl; number++; } }
结果如下图:
DT的实现并不忠实于ADT的另一个原因是:实现中的操作不一定能够完全按照相应的ADT的操作一样的方式执行。
。。。。
关于《4、程序员可定义的新数据类型(Typedef和枚举)》和《5、指针》的介绍将在下一篇博文《抽象数据类型(ADT)入门(二)》中做详细的介绍。