数据结构与算法--绪论
程序设计 = 数据结构 + 算法
数据结构通过算法来实现操作
算法根据数据结构来设计程序
基本概念和术语
数据
对客观事物的符号表示,是所有能够输入到计算机中并能被计算机程序处理的符号的总称。
例如:整数、“对弈树”中的格局
数据元素
数据的基本单位
例如:“对弈树”中的一个格局,书目信息中的一条书目
数据对象
性质相同的数据元素的集合,是数据的子集
例如:
例如:整数数据对象{0,1,2……}、字母字符数据对象{a,b,c……}
数据项
一个数据元素可以由若干个数据项组成。数据项是数据不可分割的最小单位
例如:一条书目信息是由书名、作者名、分类等多个数据项组成的。
数据结构
相互之间存在一种或多种特定关系的数据元素的集合。
通常,数据元素都不是孤立存在的,在它们之间存在着某种联系,这种数据元素相互之间的关系成为结构。
基本结构
- 集合:数据元素同属关系
- 线性关系:数据元素之间一对一
- 树形结构:数据元素之间一对多
- 图状结构:数据元素之间多对多
形式定义
数据结构是一个二元组 Data_Structure = (D , S)
其中,D是数据元素的有限集,S是D上关系的有限集。
例如:复数 Complex = ( C , R ),其中,C是含有两个实数的集合{c1,c2},R = {P},而P是定义在集合C上的一种关系{<c1,c2>},其中有序偶<c1,c2>表示复数实部c1,虚部c2-----具体内容可以参考离散数学二元关系等章节。
逻辑结构和物理结构
逻辑结构:描述了数据元素之间存在的逻辑关系,又称为抽象数据结构、数据的结构,影响算法设计(例如,线性表中前驱后继关系,树中父子关系)
物理结构:数据结构在计算机内的表示/存储方式,包括数据元素的表示和逻辑关系的表示,又称为存储结构,影响算法实现
存储结构
存储结构包括数据元素的表示以及数据元素之间关系的表示。
数据元素的表示
通常用位串表示一个数据元素(例如,使用一个字节表示一个字符,四个字节表示一个整数等等)
如果数据元素是由若干个数据项组成,则用对应于各个数据项的位字串连接而成的位串表示。
数据元素之间关系的表示
顺序存储结构
借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系(顺序映像)
链式存储结构
借助指示元素存储地址的指针来表示数据元素之间的逻辑关系(非顺序映像)
数据类型基本观点
数据类型
一个值的结合和定义在这个值集上的一组操作的总称。(例如:整型:整数的集合以及定义在其上的操作(加减乘除等))
按照值的不同性质,高级程序语言的数据类型可以分为两类
- 原子类型:值时不可分解的、非结构的(例如:C语言中的基本类型(整型、实型、字符型))
- 结构类型:值由若干成分按某种结构组成。可分解。(例如:数组,结构体,文件)结构类型可以看成是一种数据结构和定义在其上的一组操作组成。
抽象数据类型
一个数学模型以及定义在该模型上的一组操作
数据类型将数据结构(数据元素、数据关系)和数据操作封装在一起,构成对象类
模块内部给出这些数据的定义、表示及其操作的细节,而在模块外部使用的只是抽象的数据和抽象的操作。
ADT = {值域} +{值域上的操作}
形式定义
抽象数据类型是一个三元组 ( D , S , P )
其中,D是数据对象、数据元素的有限集;S是D上关系的有限集;P是对D的基本操作的有限集。
多行数据类型
是指其值的成分不确定的数据类型,但是无论其元素具有何种特性,元素之间的关系不变,对元素的基本操作不变。
例如:C++中使用函数模板或者类模板;抽象数据类型Triplet,其元素e1,e1,e3可以是整型、字符型等。
算法
定义
算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每一条指令表示一个或多个操作。
算法的五个重要特性
- 有穷性:在有穷步内结束
- 确定性:操作无二义性,唯一可执行路径
- 可行性:操作可以通过有限次已有基本运算实现
- 输入:零个或多个输入
- 输出:一个或多个输出
算法设计的要求
- 正确性:正确反映需求
- 可读性:有助于理解、调试和维护
- 健壮性:完备的异常和出错处理
- 高效率+低存储:时间和空间的要求
算法效率
时间度量
从算法中选取一种对于研究的问题来说是基本操作的原操作,以该基本操作重复执行的次数作为算法执行的时间度量。
频度:语句重复执行的次数,称为该语句的频度,记作f(n)。
实际上我们所关心的主要是一个算法所花时间的数量级,即取算法各基本操作的最大频度数量级
时间复杂度:算法执行时间度量,记作T(n) = 0( maxlevel(f(n)) )
有时,算法中基本操作重复执行的次数随问题的输入不同而不同,通常分析最坏情况下的时间复杂度。
空间复杂度
算法在运行过程中临时占用存储空间大小的一个度量。
存储空间固定部分:主要包括算法所需工作单元所占用的空间,这部分属于静态空间
存储空间可变部分:主要包括其于问题规模有关的数组所占空间,递归工作栈所用空间,以及在算法运行过程中适用malloc(new)和free(delete)使用的空间。
如果空间大小仅与问题规模n有关,可以通过分析算法,找出所需空间大小与n的一个函数关系,就能得到所需空间大小。
动态分配若使用了delete或free需要具体分析内存空间使用