1. 引言
- 著名的瑞士计算机科学家N.Wirth提出:算法+数据结构=程序,这里的数据结构指的是数据的逻辑结构和存储结构,而算法是对数据运算的描述。
- 对于数值类型的计算问题可以抽象成数学模型由数学方程解决,而对于非数值计算的问题,例如,计算机文件系统,城市交通网络以及工程管理的活动安排等都是非数值计算问题。
- 数据结构研究的是非数值计算的计算机操作对象以及它们之间的关系和操作。
2. 术语
- 数据:描述客观事物的数,字符以及能够输入计算机且被其处理的符号记录的集合。可以分为数值型(整数和实数)和非数值型(文字,图形,图像,声音等)。
- 数据元素:数据的基本单位。例如,表格的一行,树的一个结点,图的一个顶点。可以理解为集合中的一个个体。
- 数据项:具有独立含义的最小标识单位,不可拆分,例如,图书的书名,作者。
- 数据对象:具有相同性质的数据元素集合,是数据的一个子集。
- 数据类型:一个值的集合和定义在这个值集上的一组操作。
- 抽象数据类型(ADT):不考虑计算机内的具体存储结构和算法,是定义了相关操作运算的一个数学模型。
3. 基本概念
- 数据结构包含三个方面的内容:逻辑结构,存储结构,数据的运算。
3.1 逻辑结构
逻辑结构是从逻辑关系上描述数据,它与数据元素的存储结构无关,是独立于计算机的,是从具体问题抽象出来的数学模型。可分为线性结构和非线性结构。
线性结构:数据元素之间存在一对一(线性)的关系,且结构中只有一个开始节点和一个终端结点,其余结点都是仅有一个直接前趋(与其相邻且在它前面的结点)和一个直接后继(与其相邻且在它后面的结点)。典型的线性结构有:线性表,队列,栈,串。
非线性结构:数据元素之间存在一对多或者多对多的关系,例如,树,图,网。
3.2 存储结构
存储结构又称为物理结构,是指数据元素及其关系在计算机内的存储方式(即映像)。
四种基本存储方法:
顺序存储:把逻辑上相邻的结点存储在物理位置也相邻的连续存储单元里,即逻辑相邻且物理相邻,通常用高级语言中的数组来描述。
链式存储:用一组不一定连续的存储单元存储逻辑上相邻的数据元素,元素间的逻辑关系由附加的指针域表示,通常用高级语言中的指针来描述指针域。
索引存储:在存储元素的信息时建立附加的索引表(通常的形式是(关键字,地址)),其中的关键字可以唯一确定一个元素。
散列(哈希)存储:由散列函数直接计算出元素的存储地址。
3.3 数据的运算
数据的运算是对数据元素施加的操作,常见的有:插入,删除,查找,排序等。
4. 算法分析
- 算法:由若干条指令组成的有穷序列。通俗地讲,算法是求解问题的过程或步骤。
- 算法必须满足:输入,输出,有穷性(包括每一条指令的次数和时间),确定性和可行性。
- 算法设计要求:正确性,可读性,健壮性,高效性。
- 算法主要考虑:时间复杂度和空间复杂度,分别对应是执行算法所耗费的时间和空间。有两种统计方法:事后统计和事前分析,而我们通常采用后者。
4.1 时间复杂度
算法耗费时间= Σ \Sigma Σ(每条语句的执行次数(即频度) × \times ×该语句执行一次所需要的时间)
然而语句执行一次所需要的时间随机器而异,故可以直接讨论次数,脱离软硬件来分析一个算法的性能。
时间复杂度记为:T(n)=O( f f f(n)),其中 f f f(n)是问题规模n的某个函数。
下面通过一个具体的例子分析时间复杂度:
(1)for(i=1;i<=n;i++) //执行n+1次
(2) for(j=1;j<=n;j++) //执行n(n+1)次
(3) a[i][j]=0; //执行n^2次
于是,所有语句频度和为T(n)=n+1+n(n+1)+n
2
^2
2=2n
2
^2
2+2n+1,可以看出,T(n)就是矩阵阶数n的函数,即问题规模,一个算法的时间复杂度就是该算法的时间耗费,是所求问题规模n的函数。当n足够大时,T(n)和n
2
^2
2之比是一个不为零的常数,则称T(n)和n
2
^2
2同阶,于是,把T(n)=O(n
2
^2
2)称为该算法的渐进时间复杂度,通常,将渐进时间复杂度简称为时间复杂度。
注意:(1)通常情况下,时间复杂度是由嵌套最深的语句的频度决定的;
(2)
f
f
f(n)一般为算法中频度最大的语句,例如,
f
f
f(n)=n
2
^2
2就是该算法中语句(3)的频度
(3)如果算法的运行次数可以数出来,则对于任意一个常数的时间复杂度记为O(1),
常用的时间复杂度有O(1),O(n),O(
log
2
n
\log_2n
log2n),O(n
log
2
n
\log_2n
log2n),O(n
2
^2
2),O(n
3
^3
3),O(2
n
^n
n),O(n!)等,且依次递增。
4.2 空间复杂度
通常记为S(n)=O(
f
f
f(n))。