1.1 基本概念
1.数据(data) 是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并
被计算机程序处理的符号的总称。它是计算机程序加工的"原料"。
2.数据元素(data element) 是数据的基本单位,在计算机程序中通常作为一个整体进行考
虑和处理。有时,一个数据元素可由若干个数据项(data item) 组成,例如,一本书的书目信
息为一个数据元素,而书目信息中的每一项(如书名、作者名等)为一个数据项。数据项是数
据的不可分割的最小单位。
3.数据对象(data object) 是性质相同的数据元素的集合,是数据的一个子集。例如,整数
数据对象是集合 N={O , 士 1 ,士 2 ,...} ,字母
4.数据结构 数据结构是指互相之间存在着一种或多种关系的数据元素的集合。 数据结
构是一个二元组 Data_Structure =(D,R),其中,D 是数据元素的有限集,R 是 D 上关
系的有限集。
5.逻辑结构:是指数据之间的相互关系。上述数据结构的定义仅是对操作对象的一种数学描述,换句话说,是从操作对象抽象数据的逻辑结构出来的数学模型.结构定义中的"关系" 描述的是数据元素之间的逻辑关系,通常分为四类结构:
(1)集合:结构中的数据元素除了同属于一种类型外,别无其它关系。
(2)线性结构:结构中的数据元素之间存在一对一的关系。
(3)树型结构:结构中的数据元素之间存在一对多的关系。
(4)图状结构:结构中的数据元素之间存在多对多的关系。
6.存储结构:是指数据结构在计算机中的表示,又称为数据的物理结构。数据的逻辑结
构和物理结构是密切相关的两个方面,任何一个算法的设计取决于选定的数据(逻辑)结构,
而算法的实现依赖于采用的存储结构。通常由四种基本的存储方法实现:
(1)顺序存储方式。数据元素顺序存放,每个存储结点只含一个元素。存储位置反映
数据元素间的逻辑关系。存储密度大。但有些操作(如插入、删除)效率较差。
(2)链式存储方式。每个存储结点除包含数据元素信息外还包含一组(至少一个)指
针。指针反映数据元素间的逻辑关系。这种方式不要求存储空间连续,便于动态操作(如插
入、删除等),但存储空间开销大(用于指针),另外不能折半查找等。
(3)索引存储方式。除数据元素存储在一组地址连续的内存空间外,还需建立一个索
引表,索引表中索引指示存储结点的存储位置(下标)或存储区间端点(下标)。
(4)散列存储方式。通过散列函数和解决冲突的方法,将关键字散列在连续的有限的
地址空间内,并将散列函数的值解释成关键字所在元素的存储地址。其特点是存取速度快,
只能按关键字随机存取,不能顺序存取,也不能折半存取。
7.数据类型(data type) 是和数据结构密切相关的一个概念,它最早出现在高级程序语言
中,用以刻画(程序)操作对象的特性.在用高级程序语言编写的程序中, 每个变量、常量或表
达式都有一个它所属的确定的数据类型。类型明显或隐含地规定了在程序执行期间变量或表
达式所有可能取值的范围,以及在这些值上允许进行的操作.因此数据类型是一个值的集合和
定义在这个值集上的一组操作的总称.例如, C 语言中的整型变量,其值集为某个区间上的
整数〈区间大小依赖于不同的机器). '定义在其上的操作为加、减、乘、除和取模等算术运算。
8.抽象撒据类型(Abstract Data Type ,简称 ADT) 是指一个数学模型以及定义在该模型
上的一组操作.抽象数据类型的定义仅取决于它的一组逻辑特性,而与其在计算机内部如何表
示和实现无关,即不论其内部结构如何变化,只要它的数学特性不变,都不影响其外部
的使用。
抽象数据类型和数据类型实质上是一个概念.例如,各个计算机都拥有的"整数"类型是一
个抽象数据类型,尽管它们在不同处理器上实现的方法可以不同,但由于其定义的数学特性
相同,在用户看来都是相同的.因此,"抽象"的意义在于数据类型的数学抽象特性。
抽象数据类型可用以下三元组表示:(D,S,P)
其中, D 是数据对象, S 是 D 上的关系集, P 是对 D 的基本操作集。
严老师版教材采用以下格式定义抽象数据类型:
ADT 抽象数据类型名{
数据对象: (数据对象的定义〉
数据关系: (数据关系的定义〉
基本操作: (基本操作的定义〉
}ADT 抽象数据类型名
其中,数据对象和数据关系的定义用伪码描述,基本操作的定义格式为
基本操作名(参数表)
初始条件: (初始条件描述〉
操作结果: (操作结果描述〉
基本操作有两种参数:赋值参数只为操作提供输入值;引用参数以&打头,除可提供输入
值外,还将返回操作结果。"初始条件"描述了操作执行之前数据结构和参数应满足的条件,
若不满足,则操作失败,并返回相应出错信息。"操作结果"说明了操作正常完成之后,数据
结构的变化状况和应返回的结果。若初始条件为空,则省略之。
1.2 算法和算法复杂性分析
1.算法(algorithm) 是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一
条指令表示一个或多个操作;此外,一个算法还具有下列 5 个重要特性:
(1) 有穷性:一个算法必须总是〈对任何合法的输入值)在执行有穷步之后结束,且每
一步都可在有穷时间内完成。
(2) 确定性:算法中每一条指令必须有确切的含义,读者理解时不会产生二义性并且,
在任何条件下,算法只有惟一的一条执行路径,即对于相同的输人只能得出相同的输出。
(3) 可行性:一个算法是能行的, 即算法中描述的操作都是可以通过已经实现的基
本运算执行有限次来实现的。
(4) 输入:一个算法有零个或多个的输入,这些输入取自于某个特定的对象的集合。
(5) 输出:一个算法有一个或多个的输出,这些输出是同输入有着某些特定关系的。
2.算法效率的度量
算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗的时间来度量。而
度量一个程序的执行时间通常有两种方法。
(1)事后统计的方法因为很多计算机内部都有计时功能,有的甚至可精确到毫秒级,
不同算法的程序可通过一组或若干组相同的统计数据以分辨优劣。但这种方法有两个缺陷:
一是必须先运行依据算法编制的程序;二是所得时间的统计量依赖于计算机的硬件、软件等环
境因素,有时容易掩盖算法本身的优劣。因此人们常常采用另一种事前分析估算的方法。
(2) 事前分析估算的方法一个用高级程序语言编写的程序在计算机上运行时所消耗的
时间取决于下列因素:
①依据的算法选用何种策略:
②问题的规模,例如求 100 以内还是 1000 以内的素数;
③书写程序的语言,对于同一个算法,实现语言的级别越高,执行效率就越低;
④编译程序所产生的机器代码的质量; ⑤机器执行指令的速度。
显然,向一个算法用不同的语言实现,或者用不同的编译程序进行编译,或者在不同的
计算机上运行时,效率均不相同.这表明使用绝对的时间单位衡量算法的效率是不合适的。撇
开这些与计算机硬件、软件有关的因素,可以认为一个特定算法"运行工作量"的大小,只依
赖于问题的规模〈通常用整数量 n 表示) ,或者说,它是问题规模的函数。
一般情况下,算法中基本操作重复执行的次数是问题规模 n 的某个函数 f(n),算法的时
间量度记作
T(n) = O(f( n))
它表示随问题规模 n 的增大,算法执行时间的增长率和 f(n)的增长率相同,称做算法的
渐近时间复杂度(asymptotic time complexity) ,简称时间复杂度。
显然,被称做问题的基本操作的原操作应是其重复执行次数和算法的执行时间成正比的
原操作,多数情况下它是最深层循环内的语句中的原操作,它的执行次数和包含它的语句的
频度相同.语句的频度(frequency count) 指的是该语句重复执行的次数,例如,在下列 3 个程
序段中:
(a) { ++ x; s = 0,}
(b) for (i = 1; i<n; ++i) {++x; s += x;}
© for (j = 1, j<=n; ++ j)
for (k=1; k<=n; ++k) {++x; s += x;}
含基本操作++x 的语句的频度分别为 1 、n 和 n^2,则这 3 个程序段的时间复杂度分别
为 O(1)、O(n)和 O(n^2 ),分别称为常量阶、线性阶和平方阶.算法还可能呈现的时间复杂
度有对数阶 O(log n) 、指数阶 0(2") 等。
注意:有的情况下,算法中基本操作重复执行的次数还随问题的输入数据集不同而不同。
常见的渐进时间复杂度有:Ο(1)<Ο(log2n)<Ο(n)<Ο(nlog2n)<Ο(n
2)<Ο(n
3)<Ο(2
n) <O(n!)
<O(n
n)。
3.算法的空间复杂度:是对一个算法在运行过程中临时占用的存储空间大小的量度。只
需要分析除输入和程序之外的辅助变量所占额外空间。
原地工作:若所需额外空间相对于输入数据量来说是常数,则称此算法为原地工作,空
间复杂度为 O(1)。