目录
数据结构
数据结构是一门研究非数值计算的程序设计问题中计算机的数据元素以及它们之间的关系和运算等的学科。
一、基本概念和术语
- 数据:描述客观事物的符号,是计算机中可操作的对象,是能被计算机识别,并输入给计算机处理的符号集合。数据包括整型、实型等数值类型也包括图像、视频这些非数值类型。
- 数据元素:是数据的基本单位,在计算机中通常作为一个整体来处理。一个数据元素可由若干个数据项组成。
- 数据项:数据项是数据不可分割的最小单位。如一本书是一个数据元素,书的页数,价格,作者为数据项。
- 数据对象:是性质相同(指数据元素具有相同数量和类型的数据项)的数据元素的集合,实数集的一个子集。
- 数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。通常为4类基本结构:集合、线性结构、树形结构、图状结构或网状结构
把数据结构分为逻辑结构和物理结构
逻辑结构:它包括问题所涉及的数据对象,以及数据对象内部各个数据元素之间的特定关系。
物理结构:又称存储结构,它包括全体数据元素以及数据元素至之间的特定关系在计算机内部的表达。
数据元素之间的关系在计算机中有两种不同的表示方法:顺序映像和非顺序映像,相应的得到两种不同的存储结构:顺序存储结构和链式存储结构
二、逻辑结构:指数据对象中数据元素之间的相互关系
1、集合结构:集合结构中的数据元素除了同属于一个集合外,它们之间没有其他关系。
2、线性结构:线性结构中的数据元素之间是一对一关系。
3、树形结构:树形结构中的数据元素之间存在一对多关系。
4、图形结构:图形结构的数据元素是多对多的关系。
三、物理结构:指数据结构的逻辑结构在计算机中的存储形式。
(数据是数据元素的集合,物理结构实际上就是把数据元素存储到计算机的存储器中。存储器主要是针对内存而言的,像硬盘、光盘之类的外部存储器的数据组织通常用文件结构来描述)
数据元素的存储结构形式有两种:顺序存储和链式存储
1、顺序存储结构:把数据元素存放在地址连续的存储单元里,其数据间的逻辑关系和物理关系是一致的。
2、链式存储结构:把数据结构放在任意的存储单元里,这组存储单元可以是连续的也可以是不连续的。
四、数据类型(Data Type)
数据类型是和数据结构密切相关的一个概念,它最早出现在高级程序语言中,用来刻画程序操作对象的特性。数据类型是一个值的集合和定义在这个值集上的一组操作的总称。
按“值”的不同特性,高级程序语言中的数据类型可分为两类:一类是非结构的原子类型,原子类型的值是不可分解的,如C语言中的基本类型(整型、实型、字符型和枚举类型)、指针类型和空类型。另一类是结构类型,结构类型的值是由若干成分按某种结构组成的,是可以分解的,并且它的成分可以是非结构的,也可以是结构的。
五、抽象数据类型(Abstract Data Type)
抽象数据类型指一个数学模型以及定义在该模型上的一组操作。
-
抽象数据类型的定义只涉及数学模型的逻辑特性,不涉及该模型的具体实现细节。
-
不管内部采用什么技术方法来实现这个抽象数据类型,只要模型的数学特性不变,都不会影响它的外部使用。从而使外部使用和内部实现分离。
-
“抽象”的目的就是让人们集中精力把握问题的本质,研究解决问题的算法核心,抛开繁琐的实现细节,从而使问题得到简化。
-
“抽象”可以按一定的层次逐步提高抽象的程度。层次越高,细节就越少,使用就越方便。
算法
一、算法的定义
算法(algorithm)是对特定问题求解步骤的一种描述,它是指令的有限序列,其中每条指令表示一个或多个操作。
算法的5个重要特性:
- 有穷性:算法必须能在执行有穷步骤之后结束,每一步骤都能在有限时间内完成
- 确定性:算法的每一个步骤必须是确切定义的。并且,对于一种输入,算法只有一条执行路径,即对于相同的输入只能得到相同的输出
- 能行性:算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现
- 有输入:一个算法有零个或多个输入,这些输入取自某个特定的对象的集合
- 有输出:一个算法有一个或多个输出,这些输出是同输入有着某些特定关系的量
二、算法设计的要求
- 正确性(correctness)
- 易读性(readability)
- 健壮性(robustness)
- 高效率
三、算法效率分析
1、时间耗费:渐近时间复杂度
- 语句的频度:算法种某条语句重复执行的次数
- 算法的时间耗费:(其中表示语句i执行一次所耗费的时间;m表示算法中可执行语句的个数)
-
算法的时间复杂度:语句执行的时间与机器的性能有关,编译程序的代码质量有关,语句的种类有关。为了排除这些与算法无关的因素,取=单位1。这样算法的时间耗费T就简化为统计算法中所有语句的执行次数:
- 很多情况下,T是问题规模为n的函数T(n),例如:
计算n阶方阵的乘积C=A×B
for(i=1; in; i++) (n+1)次
for(j =1; j<=n; j++){ n(n+1)次
C[i][j]=0; 次
for(k=1; k<=n; k++) (n+1)次
C[i][j]+=A[i][k]*B[k][j] ; 次
}
计算得时间复杂度:T(n)=(n+1) + n(n+1) + + (n+1) + = 2 + 3 + 2n + 1 = O()
可记为:T(n) = O()
用一个与T(n)同阶的简单函数表示算法的时间耗费:
设f(n)是一个已知的简单函数,且满足,则T(n)与f(n)同阶,记为T(n)=O(f(n))
O是Order(数量级)的第一个字母,它允许用“=”代替“≈”。
如:+3+2n=O()
我们用O(f(n))来做为算法时间耗费的度量,称为算法的渐进时间复杂度,简称为算法的时间复杂度。
由此,时间复杂度只精确到数量级,不必对每条语句的频度进行精确求和计算,只考虑算法中执行次数最多的语句执行次数就行,如以上例子中执行次数最多的语句执行了次,则T(n) = O()
对于一些与数据初始状态有关的不确定问题,可以采用简化的方法估计时间复杂度:如按最坏的情况估算、按平均的情况估算
常用的时间复杂度按照耗费的时间从小到大依次是:O(1)<O(logn)<O(n)<O(nlogn)<O(n²)<O(n³)<O(2ⁿ)<O(n!)
2、空间耗费:渐近空间复杂度
算法执行期间需要占用的存储空间由3部分组成:
1、数据元素集合所占的空间;
2、程序本身所占的空间;
3、辅助变量所占的空间(辅助空间)
类似于算法的时间复杂度,用算法的空间复杂度来度量所需存储空间,记作:S(n) = O(f(n))