1、教 材,数据结构(C语言版)严蔚敏 吴伟民编著清华大学出版社,第一章 绪论,1.1 数据结构讨论的范畴,算法+数据结构 = 程序设计算法即处理问题的策略数据结构即为问题的数学模型。数值计算问题的数学模型通常可用一组线性或非线性的代数方程组或微分方程组来描述大量非数值计算问题的数学模型正是本门课程要讨论的数据结构。,例1、电话号码查询系统设有一个电话号码薄,它记录了N个人的名字和其相应的电话号码,假定按如下形式安排:(a1,b1)(a2,b2)(an,bn)其中ai,bi(i=1,2n) 分别表示某人的名字和对应的电话号码要求设计一个算法,当给定任何一个人的名字时,该算法能够打印出此人的电话号码
2、,如果该电话簿中根本就没有这个人,则该算法也能够报告没有这个 人的标志。,算法的设计,依赖于计算机如何存储人的名字和对应的电话号码,或者说依赖于名字和其电话号码的结构。数据的结构,直接影响算法的选择和效率。上述的问题是一种数据结构问题。可将名字和对应的电话号码设计成:二维数组、表结构、向量。比如,名字和其电话号码逻辑上可安排成N元向量的形式,它的每个元素是一个数对(ai , bi), 1in 数据结构还要提供每种结构类型所定义的各种运算的算法。,例2、图书馆的书目检索系统例3、人-机对弈问题例4、多岔路口的交通灯管理问题以上例子中的数学模型正是数据结构要讨论的问题。数据结构是一门讨论“描述现实
3、世界实体的数学模型(非数值计算)及其上的操作在计算机中如何表示和实现“的学科。,1.2 与数据结构相关的基本概念,1.2.1 基本概念和术语 数据 是所有能被输入到计算机中,且能被计算机处理的符号(数字、字符等)的集合,它是计算机操作对象的总称。 是计算机处理的信息的某种特定的符号表示形式。,数据元素 是数据(集合)中的一个“个体”,在计算机中通常作为一个整体进行考虑和处理,是数据结构中讨论的“基本单位”。两类数据元素: 一类是不可分割的“原子”型数据元素,如:整数“5”,字符 “N” 等; 另一类是由多个款项构成的数据元素,其中每个款项被称为一个“数据项”。数据项是数据结构中讨论的“最小单位
4、”。,数据对象性质相同的数据元素的集合。是数据的一个子集。,1.2.2 数据结构 数据结构是带“结构”的数据元素的集合。“结构”即指数据元素之间存在的关系。 数据结构的形式定义为: 数据结构是一个二元组 Data_Structures = ( D,S ) 其中:D是数据元素的有限集, S是D上关系的有限集。例 复数的数据结构定义如下:Complex=(C,R)其中:C是含两个实数的集合C1,C2,分别表示复数的实部和虚部。R=P,P是定义在集合上的一种关系C1,C2。, 数据结构包括:1. 数据逻辑结构:是对数据元素之间存在的逻辑关系的描述,它可以用一个数据元素的集合和定义在此集合上的若干关系
5、表示。 2. 数据物理结构:是数据逻辑结构在计算机中的表示和实现(逻辑结构在存储器中的映象),故又称数据“存储结构”。它包含数据元素的映象和关系的映象。3. 对数据元素的操作:对每一个数据结构而言,必定存在与它密切相关的一组操作。,数据的逻辑结构可归结为以下四类:一、集合 结构中的数据元素除了同属于一种类型外,别无其它关系。二、线性结构 结构中的数据元素之间存在一对一的关系。三、树型结构 结构中的数据元素之间存在一对多的关系。四、图状结构或网状结构 结构中的数据元素之间存在多对多的关系。,数据的物理结构可分为(关系的表示方法): 一. “顺序映象”。以 “y 相对于 x 的存储位置” 表示 “
6、y 是x的后继”,由此得到的数据存储结构为“顺序存储结构”。 二. “链式映象“。以和x绑定在一起的附加信息(指针)表示后继关系,这个指针即为 y 的存储地址,由此得到的数据存储结构为“链式存储结构“。,存储结构的描述方法:随编程环境的不同而不同,当用高级程序编程时,通常可用高级编程语言中提供的数据类型描述之。例 当以“顺序存储结构”表示长度为3的长整数表时,可将它定义为: typedef int Long_int3;,不同数据结构其操作集不同,但下列操作必不可缺: 1) 结构的生成; 2) 结构的销毁; 3) 在结构中查找满足规定条件的数据元素; 4) 在结构中插入新的数据元素; 5) 删除
7、结构中已经存在的数据元素; 6) 遍历。,1.2.3 数据类型和抽象数据类型 数据类型:在一种程序设计语言中,变量所具有的数据种类。是一个“值”的集合和定义在此集合上的“一组操作”的总称。例、在C语言中,数据类型包括基本类型和构造类型基本类型:整型、浮点型、字符型构造类型:数组、结构、联合、指针、枚举型、自定义抽象数据类型(Abstract Data Type 简称 ADT):是指一个数学模型以及定义在此数学模型上的一组操作。 例如,矩阵的抽象数据类型定义为,矩阵是一个由 m x n 个数排成 m 行 n 列的表,它可以进行初等变换、相加、 相乘、求逆、等运算。,抽象数据类型有两个重要特性:数
8、据抽象 用ADT描述程序处理的实体时,强调的是其本质的特征、其所能完成的功能以及它和外部用户的接口(即外界使用它的方法)。 数据封装 将实体的外部特性和其内部实现细节分离,并且对外部用户隐藏其内部实现细节。,抽象数据类型的形式描述为:ADT = ( D,S,P ) 其中:D 是数据对象, S 是 D 上的关系集, P 是 D 的基本操作集。 抽象数据类型的形式定义为: ADT 抽象数据类型名 数据对象: 数据对象的定义 数据关系: 数据关系的定义 基本操作: 基本操作的定义 ADT 抽象数据类型名,例如,抽象数据类型“复数”的定义为: ADT Complex 数据对象:D = e1,e2 |
9、e1,e2 RealSet 数据关系:R1 = | e1是复数的实 部,e2是复数的虚部 基本操作: InitComplex( &Z, v1, v2 ) 操作结果:构造复数Z,其实部和虚部 分别被赋以参数v1和v2的值。,DestroyComplex( &Z) 初始条件:复数已存在。 操作结果:复数Z被销毁。 GetReal( Z, &realPart ) 初始条件:复数已存在。 操作结果:用 realPart 返回复数Z的实部值。 GetImag( Z, &ImagPart ) 初始条件:复数已存在。 操作结果:用 ImagPart 返回复数Z的虚部值。 Add( z1,z2, &sum )
10、 初始条件:z1,z2 是复数。 操作结果:用sum返回两个复数z1,z2的和值。 ADT Complex,1.3 算法和算法分析 1.3.1 算法及其设计原则 算法是对问题求解过程的一种描述,是为解决一个或一类问题给出的一个确定的、有限长的操作序列。一个算法必须满足以下五个重要特性: (1) 有穷性:一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成。 (2) 确定性:算法中每一条指令必须有确切的含义。不存在二义性。且算法只有一个入口和一个出口。 (3) 可行性:一个算法是可行的。即算法描述的操作都是可以通过已经实现的基本运算执行有限次来实现的。(4) 有输入:一个算法有零个或
11、多个输入,这些输入取自于某个特定的对象集合。(5) 有输出:一个算法有一个或多个输出,这些输出是同输入有着某些特定关系的量。,在设计算法时,通常应考虑以下原则:首先,设计的算法必须是“正确的”,其次,应有很好的“可读性”,第三,还必须具有“健壮性”,最后,应考虑所设计的算法具有“高效率与低存储量”。,1.3.2 算法的描述 本课程讨论的数据结构和算法拟采用类C语言,它既不拘泥于某个具体的C语言,又容易转换成可以上机调试的C程序或C+程序。 (1) 数据结构的表示(存储结构)都用类型定义 (typedef) 的方式描述。基本数据元素类型约定为 ElemType,由用户在使用该数据类型时再自行具体
12、定义。 (2) 基本操作的算法都用以下形式的函数描述: 函数类型 函数名(函数参数表) / 算法说明 语句序列 / 函数名,(3) 除了函数的参数需要说明类型外,算法中使用的辅助变量可以不作变量说明,必要时对其作用给予注释。 (4)语句序列中仅包含C语言的三种基本结构:顺序结构、选择结构和循环结构。,1.3.3 算法效率的衡量方法 通常有两种衡量算法效率的方法:事后统计法:求出该算法的一个时间界限函数。缺点是,必须在计算机上实地运行程序,容易由其它因素掩盖算法本质; 事前分析估算法:收集此算法的执行时间和实际占用空间的统计资料。优点是,可以预先比较各种算法,以便均衡利弊而从中选优。 如何估算算
13、法的时间效率?,和算法执行时间相关的因素有: 1)算法所用“策略”; 2)算法所解问题的“规模”; 3)编程所用“语言”; 4)“编译”的质量; 5)执行算法的计算机的“速度”。显然,后三条受着计算机硬件和软件的制约,既然是“估算“,仅需考虑前两条。,一个算法的“运行工作量”通常是随问题规模的增长而增长,因此比较不同算法的优劣主要应该以其“增长的趋势”为准则。假如,随着问题规模 n 的增长,算法执行时间的增长率和f(n)的增长率相同,则可记作: T(n)=O(f(n) 称T(n)为算法的(渐近)时间复杂度。,“O ” 的数学含义是:如果存在两个正常数c和n0,对于所有的nn0,有f(n) cg
14、(n) 则记作 f(n)=O(g(n) 它表明算法的执行时间是和g(n)“同数量级“的。 “渐近“是相对其它时间复杂度而言,以后均简称时间复杂度。,如何估算算法的时间复杂度? 任何一个算法都是由一个“控制结构”和若干“原操作”组成的,因此一个算法的执行时间可以看成是所有原操作的执行时间之和 ( 原操作(i)的执行次数 原操作(i)的执行时间 ) 则算法的执行时间与所有原操作的执行次数之和成正比。 这种衡量效率的办法是一种增长趋势的量度。它与软硬件环境无关,只暴露算法本身执行效率的优劣。,频度:是指该语句重复执行的次数例 +x;s=0;将x自增看成是基本操作,则语句频度为,即时间复杂度为(1)如
15、果将s=0也看成是基本操作,则语句频度为,其时间复杂度仍为(1),即常量阶。例、for(i=1;i=n;+i)+x;s+=x;语句频度为:2n,其时间复杂度为:O(n),为线性阶。例、for(i=1;i=n;+i) for(j=1;j=n;+j)+x;s+=x;语句频度为:2n2其时间复杂度为:O(n2),为平方阶。,例 for(i=2;i=n;+i)for(j=2;j=i-1;+j)+x;ai,j=x;语句频度为:1+2+3+n-2=(1+n-2) (n-2)/2=(n-1)(n-2)/2=n2-3n+2时间复杂度为O(n2),为平方阶.对时间复杂度而言,只需要取最高项,并忽略常数系数。定理
16、:若A(n)=a m n m +a m-1 n m-1 +a1n+a0是一个m次多项式,则A(n)=O(n m)下面举三个例子介绍时间复杂度的估算方法。 。,例1.1 两个 n x n 的矩阵相乘。其中矩阵的“阶” n 为问题的规模。 算法 1.1 void Mult_matrix( int c, int a, int b, int n) / a、b 和 c 均为 n 阶方阵,且 c 是 a 和 b 的乘积 for (i=1; i=n; +i) for (j=1; j=n; +j) ci,j = 0; for (k=1; k=n; +k) ci,j += ai,k*bk,j; / Mult_m
17、atrix 由于是一个三重循环,每个循环从1到n,则总次数为: nnn=n3算法的时间复杂度为O (n3) 。,例1.2 对 n 个整数的序列进行选择排序。其中序列的“长度“ n 为问题的规模。 算法 1.2 void select_sort(int a, int n) / 将 a 中整数序列重新排列成自小至大有序的整数序列。 for ( i = 0; i n-1; +i ) j = i; for ( k = i+1; k n; +k ) if (ak aj ) j = k; if ( j != i ) w = aj; aj = ai; ai = w; / select_sort 算法的时间复
18、杂度为O (n2),算法中的控制结构是两重循环,所以基 本操作是在内层循环中的“比较”,它的重复 执行次数是,例1.3 对 n 个整数的序列进行起泡排序。其中序列的“长度” n 为问题的规模。动画 算法 1.3 void bubble_sort(int a, int n) / 将 a 中整数序列重新排列成自小至大有序的整数序列。 for (i=n-1, change=TRUE; i=1 change = TRUE / bubble_sort 算法的时间复杂度为O (n2) 。,算法中基本操作重复执行的次数随问题的输入数据集不同而不同。 最好情况:0次 最坏情况:1+2+3+n-1=n(n-1)
19、/2平均时间复杂度为:O(n2),从以上三个例子可见,算法时间复杂度取决于最深循环内包含基本操作的语句的重复执行次数。以下六种计算算法时间的多项式是最常用的。其关系为:O(1)O(logn)O(n)O(nlogn)O(n2)O(n3)指数时间的关系为:O(2n)O(n!)O(nn),1.3.4 算法的存储空间需求 算法的存储量指的是算法执行过程中所需的最大存储空间。算法执行期间所需要的存储量应该包括以下三部分: (1)输入数据所占空间; (2)程序本身所占空间; (3)辅助变量所占空间。 通常以算法的空间复杂度作为算法所需存储空间的量度。定义算法空间复杂度为 S (n) = O (g(n) 表
20、示随着问题规模n的增大,算法运行所需辅助存储量的增长率与g(n)的增长率相同。,程序代码本身所占空间对不同算法通常不会有数量级之差别,因此在比较算法时可以不加考虑;算法的输入数据量和问题规模有关,若输入数据所占空间只取决于问题本身,和算法无关,则在比较算法时也可以不加考虑;由此只需要分析除输入和程序之外的额外空间。 所需额外空间相对于输入数据量来说是常量的算法,被称作是原地工作的算法。 也和算法时间复杂度的考虑类似,若算法所需存储量依赖于特定的输入,则通常按最坏情况考虑。,本章小结,本章是为以后各章讨论的内容作基本知识的准备,介绍数据结构和算法等基本概念。 数据是计算机操作对象的总称,它是计算机处理的符号的集合,集合中的个体为一个数据元素。数据元素可以是不可分割的原子,也可以由若干数据项合成,因此在数据结构中讨论的基本单位是数据元素,而最小单位是数据项。,