![](https://i-blog.csdnimg.cn/blog_migrate/207485668d6873592bedca64bed70d9c.png)
![](https://i-blog.csdnimg.cn/blog_migrate/d8958e1c0b35dba125b6248089c03094.png)
1.基本术语概念
1.1 数据结构的基本概念
- 数据: 数据是信息的载体,符号的集合,所有能输入到计算机中并能被计算机程序处理的符号的合集,是计算机加工处理的原料。总之, 存储在计算机中可用二进制表示的内容都是数据。
- 数据元素:数据的基本单位,通常作为一个整体去考虑和处理。一个数据元素可以由若干数据项组成。
- 数据项: 构成数据元素的不可分割的最小单位,也是是具有独立含义的数据最小单位。
- 数据对象:具有相同性质的数据元素的集合,是数据的一个子集
- 数据结构:相互之间存在一种或者多种关系的数据元素的集合
举例:
一张信息表:数据对象
表中每一行个人信息: 数据元素
每一行的每一个表格的姓名,班级等: 数据项
1.2 数据结构的三要素
数据结构是研究数据及数据之间 关系的一门学科。 它包括三个方面:
1.2.1. 数据的逻辑结构
数据的逻辑结构是指数据元素之间的关系、组织方式以及相互之间的依赖关系等。它是对数据集合在逻辑上的组织和排列方式进行描述,从而使得数据能够被有效地存储、检索和处理。不同的数据逻辑结构适用于不同的应用场景和问题,合理选择和使用适当的数据逻辑结构是保证数据处理效率和准确性的关键。
任何数据结构都是由数据集和关系集组成,DS=(D,R) 其中,D表示数据元素集合 R表示数据元素之间的关系集合。
逻辑结构包括:线性结构和非线性结构两大类
线性结构:结构中的数据元素之间只存在一对一的关系,除了第一个元素,所有元素都有唯一前驱;除了最后一个元素,所有元素都有唯一后继
非线性结构又包含:树结构,图结构, 集合结构
- 树形结构:结构中数据元素之间存在一对多的关系
- 图状结构:数据元素之间是多对多的关系
- 集合结构:结构中的数据元素之间除“同属一个集合”外,别无其它
1.2.2. 数据的存储结构
(物理结构)
存储结构是指数据结构在计算机中的表示(又称映像),也称物理结构。
存储结构包括:
顺序存储:把逻辑上相邻的元素存储在物理位置也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。
链式存储:逻辑上相邻的元素在物理位置上可以不相邻,借助指示元素存储地址的指针来表示元素之间的逻辑关系。
索引存储:在存储元素信息的同时,还建立附加的索引表,索引表中的每项称为索引项,索引项的一般形式是(关键字,地址)。
散列存储:根据元素的关键字直接计算出该元素的存储地址,又称哈希(Hash)存储。
数据的存储结构会影响对数据运算的速度,和存储空间分配的方便程度。
逻辑结构独立于存储结构,存储结构依赖于逻辑结构。
1.2.3. 数据的运算
数据上的运算包括运算的定义和实现。
- 运算的定义是针对逻辑结构指出运算的功能。
- 运算的实现是针对存储结构的,指出运算的具体操作步骤。
针对于某种逻辑结构,结合实际需求,定义基本运算。
例如:逻辑结构->线性结构
线性结构基本运算:
1.查找第i个数据元素
2.在第i个位置插入新的数据元素
3.删除第i个位置的数据元素......
1.3. 数据类型和抽像数据类型
数据类型是一个值的集合和定义在此集合上的一组操作的总称。
- 原子类型。其值不可再分的数据类型。如bool 和int 类型。
- 结构类型。其值可以再分解为若干成分(分量)的数据类型(例如:结构体)。
抽象数据类型(Abstract Data Type,ADT)是抽象数据组织及与之相关的操作。ADT 用数学化的语言定义数据的逻辑结构、定义运算。与具体的实现无关。
1.定义逻辑结构(数据元素之间的关系)
2.定义数据的运算(针对现实需求应该对这种逻辑结构进行什么样的运算)
3.确定某种存储结构,实现数据结构,并实现一些对数据结构的基本运算
1.4 算法的基本概念
1.4.1 什么是算法
程序 = 数据结构+算法
数据结构:相互之间存在一种或多种特定关系的数据元素的集合,探究的是如何用数据正确地描述现实世界的问题,并存入计算机。
问题(problem):是一种计算机需要完成的任务。
算法(algorithm):解决问题的方法或者步骤,探究如何高效地处理这些数据,以解决实际问题
算法(Algorithm)是对特定问题求解步骤的一种描述,它是指令的有限序列,其中的每条指令表示一个或多个操作。
1.4.2 算法的五个特性:
- 有穷性:一个算法必须总在执行有穷步之后结束,且每一步都可在有穷时间内完成。
- 确定性:算法中每条指令必须有确定的含义,对于相同的输入只能得到相同的输出。
- 可行性:算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现。
- 输入:一个算法有零个或多个输入,这些输入取自于某个特定的对象的集合。
- 输出:一个算法有一个多个输出,这些输出是与输入有着某种特定关系的量。
1.4.3 算法设计的要求(“好”算法的特质)
- 正确性:算法应能够正确的解决问题。
- 可读性:算法应具有良好的可读性,以帮助人们理解。
- 健壮性:输入非法数据时,算法能适当地做出反应或进行处理,而不会产生莫名奇妙地输出结果,能够应对一些异常状况。
- 高效率与低存储量需求:算法执行时间短:时间复杂度低。省内存:空间复杂度低。
2. 算法的时间复杂度
2.1 基本概念
渐近算法分析(asymptotic algorithm analysis),简称算法分析 (algorithm analysis)——是一种估算方法,可以估算出当问题 规模变大时,一种算法及实现程序的效率和开销。时间复杂度 和空间复杂度是渐进算法分析的两个指标。(数量级的概念)
渐近时间复杂度
(
asymptotic time complexity
)是指评估算法编 制完成程序后,在计算机中运行所消耗的时间函数。一般情况 下,算法中基本操作重复执行的次数是问题规模n
的某个函数
f
(n)
,算法的时间度量记作:
T(n)= O(f(n)) 或
T
(n)
∈
O(
f
(n))
它表示随着问题规模n的增大,算法执行时间的增长率与f(n)的 增长率相同。由于输入的规模是影响运行时间的最主要因素, 所以经常把执行算法所需的时间T写成输入规模n的函数,记做 T(n)(T(n)为非负值)。
算法增长率
(
growth rate
)
是指当输入的问题规模增长时,算法代 价的增长速率。通过渐近复杂度分析,可以把某个算法实际的复杂 度函数表示结果化简到某个简化函数类别上
2.2 如何计算
1. 找到一个基本操作(最深层循环)
2. 分析该基本操作的执行次数x和问题规模之间的关系x=f(n)
3. x的数量级O(x)就是算法的时间复杂度T(n)
注意:
- 顺序执行的代码只会影响常数项,可以忽略。
- 只需挑循环中的一个基本操作分析它的执行次数与 n 的关系即可。
- 如果有多层嵌套循环只需关注最深层循环循环了几次。
事前预估算法时间开销T(n)与问题规模 n 的关系
![O\left(1 \right )<O(\log_{2}n)<O(n)<O(n\log_{2}n)<O(n^{2})<O(n^{3})<O(2^{n})<O(n!)<O(n^{n})](https://latex.csdn.net/eq?O%5Cleft%281%20%5Cright%20%29%3CO%28%5Clog_%7B2%7Dn%29%3CO%28n%29%3CO%28n%5Clog_%7B2%7Dn%29%3CO%28n%5E%7B2%7D%29%3CO%28n%5E%7B3%7D%29%3CO%282%5E%7Bn%7D%29%3CO%28n%21%29%3CO%28n%5E%7Bn%7D%29)
2.3 三种复杂度
最坏时间复杂度:输入数据最坏的情况
平均时间复杂度:所有输入数据等概率出现的情况
最好时间复杂度:输入数据最好的情况
2.4 严格分析规则:
(
1
)可以假设一个
时间单位
.
(
2
)执行如下的操作之一,花费的
时间计为
1
:
a
.赋值运算
b
.单一的输入
/
输出操作
c
.布尔操作,数据比较
d
.算术运算
e
.函数返回
f
.数组下标操作,指针引用
(
3
)
选择语句
(
if
,
switch
)运行时间:
条件计算
+
选择语句中运行时间最长的语句执行时间
(
4
)
循环执行时间
:
循环体执行时间
+
循环条件检查和更新操作时间
+ 创建循环的时间 通常假设循环执行的最大可能迭代数量。
(
5
)
函数调用
的运行时间:
创建函数时间(
1
)
+
所有的参数计算时间
+
函数体执 行时间
时间复杂度函数的简化分析方法
:
通常,可以采用简单分析方法计算程序或算法的运行时间,假设程序的每步执行时间为1
。
程序步
可以定义为一个语法或语义意义上的程序片段,该 片段的执行时间独立于实例特征
![](https://i-blog.csdnimg.cn/blog_migrate/62b364761058f64f9db757a1dd99beea.png)
3. 算法的空间复杂度
3.1 定义
空间复杂度指当问题的规模以某种单位从1增加到n 时,解决这个问题的算法在执行时所占用的存储空 间也以某种单位由1增加到f(n),则称此算法的空间 复杂度为f(n)。研究算法的空间复杂度,只需要分析 除了算法程序和输入数据之外的额外空间
3.2 计算方法
算法原地工作——算法所需内存空间为常量,算法空间复杂度为O(1)
-
找到额外所在空间的大小和问题规模相关的变量,分析所占空间x和问题规模n的关系x=f(n)
-
x的数量级O(x)就是算法的空间复杂度S(n)
- 找到递归调用的深度x和问题规模n的关系x=f(n)
- x的数量级O(x)就是算法的空间复杂度S(n)
4. 渐近分析
4.1 上限表示法(大O表示法)
算法运行时间的上限
(
upper bound
)就是用以估计问 题所需某种资源的复杂程度的界限函数,它表示该算法可能有的最高增长率
。算法的上限还应与输入规模n 有关。为了表示起来更简单,采用
大
O
表示法,给出函数
f(n)的一个上限。
4.1.1 【定义:O符号】:
设
f
(n)
和
g
(n)
是两个
关于整数n的非 负函数
,若
存在两个正常数c和n0
,
对所有的n>n0
,
总有
f(n)≤cg(n)
,则称
f
(n)
在集合
O
(
g
(n))
中,简记为
f(n)= O(g(n))
。其中,
常数n0是使上限成立的n的最小 值,c是某个确定的常数。
注:若
f
(n)=
T
(n)
,则对于问题的所有(如最差情况) 输入,只要输入规模足够大(即n
>
n
0
),算法总能 在c
g
(n)
步以内完成
4.1.2 例题
【例
1
】(线性函数)考察
T
(N) = 3N+ 2
,
T
(N)
是一个
线性变化的函数。
(
1
)当
n≥2
时,
3n+ 2≤3n+n
=
4n
,所以
T
(n)=
O
(n)
其中:n
0
=2
,
c=4
(
2
)当
n≥1
时,
3n+ 2≤3n+ 2n= 5n
,所以
T
(n)=
O
(n)
其中:n
0
=1
,
c=5
对于两组
n
0
和
c
的取值都满足
n
的大
O
定义,也即它们都 是线性函数(对于一定的n
)。
因此,用来满足大
O
定义的
c
和
n
0
的值并不重要,因为 只需说明
T
(n)
在
O
(
g
(n) )
中
即可。
2023-10-8
西交软件科创团队收集整理,西交计算机
814
和
912
考
【例
2
】(平方函数)考虑冒泡排序算法,T
(n)= c
1
(n(n−1))∕2
。
T
(n)
是一个平方函数。
如果比较数组中相邻元素需要的时间为
c
1
(
c
1
为正数),那么 在最差情况下,n
>
1
时,
c
1
[n(n−1)]∕2≤c
1’
n
2
。所以
T
(n)=
O
(n
2
)
, 其中:n
0
=1
,
c=c
1’
。
【例
3
】(立方函数)某一算法最差情况下
T(n)=c
1
n
3
+c
2
n
2
+c
3
n
, c1
,
c
2
,
c
3
为正数。
若
n
>
1
,
c
1
n
3
+c
2
n
2
+c
3
n≤
(
c
1
+c
2
+c
3
)
n
3
。取
c=c
1
+c
2
+c
3
,
n
0
=1
, 有T(n)≤cn
3
,则
T
(n)=
O
(n
3
)
。
【例
4
】(常数函数)
当
T (n)
是一个常数时,如
T (n) = 10
,由 于T(n) = 10≤10 * 1
,所以
T
(n)=
O
(1)
,其中:
n
0
=0
,
c=10
。
4.1.3 定理
![](https://i-blog.csdnimg.cn/blog_migrate/375b354e64bf901616d099d3e2a3efd6.png)
4.1.4 化简法则
传递性
:
如果
f
(n)=
O
(
g
(n))
,且
g
(n)=
O
(
h
(n))
,则
f
(n)=
O
(
h
(n))
。 如n=
O
(n
2
)
且
n
2
=
O
(n
3
)
,则
n=
O
(n
3
)
。该规则说明,如果
g(n)
是算法 代价函数的一个上限,则g(n)
的任意上限也是该算法代价的上限。
在实际问题中,
总是试图找到一个最“紧”的上限
系数提取
:
如果
f
(n)=
O
(k
g
(n))
,对常量
k>0
,则
f
(n)=
O
(g(n))
。如5n=
O
(n)
,
100n
2
=
O
(n
2
)
。该规则说明大
O
表示法中的常数因子无 关紧要。对于Ω
和
Θ
表示法同样有这样的性质。
加法规则
:
如果
f
1
(n)=
O
(g
1
(n))
,且
f
2
(n)=
O
(g
2
(n))
,
则
f
1
(n)+
f
2
(n)=
O
(max(g
1
(n), g
2
(n)))
。
如
10n=
O
(n)
,
2n
2
=
O
(n
2
)
,所以
10n+2n
2
=
O
(n
2
)
。多项式 在 (n
的最高次幂
)
中,如
7n
6
-10n
4
+n
3
+12n+37=
O
(n
6
)
。该 规则说明并列程序段中只需要考虑一段程序中资源开销 较大的部分
乘法规则
:
如果
f
1
(n)=
O
(
g
1
(n))
,且
f
2
(n)=
O
(
g
2
(n))
,
则
f
1
(n)*
f
2
(n)=
O
(
g
1
(n)*
g
2
(n))
。
4.2 下限表示法(大Ω表示法)
同上限表示法一样,算法运行时间的下限也是估计 问题所需某种资源的复杂程度的界限函数,它表示该算 法可能有的最小增长率。与大O表示法类似,用符号大 Ω来估算函数f(n)的下限值。
4.2.1 【定义:Ω符号】
假设
f
(
n
)
和
g
(
n
)
是关于整数
n
的非负函数,
若存在两个正常数
c
和
n
0
,对于
n≥n
0
,有
f
(n)≥ c
g
(n)
,则
称
f
(n)
在集合
Ω
(
g
(n))
中。简记为
f
(n)=
Ω
(
g
(n))
4.2.2 例题
【例
1-9
】对于所有的
n
,有
T
(n) = 3n+ 2 > 3n
,因此
T
(n)=
Ω
(n)
。 同样地, T
(n) = 3n+ 3 > 3n
,所以有
T
(n)=
Ω
(n)
。 因而3n+ 2
和
3n+ 3
都是带有下限的线性函数。
【例
1-10
】某一算法平均情况下
T
(n)= c
1
n
3
+c
2
n
2
+c
3
n
,其中: c1
,
c
2
,
c
3
为正数,则有:
c
1
n
3
+c
2
n
2
+c
3
n≥c
1
n
3
(
n
>
1
) 因此,取c=c
1
,
n
0
=1
,有
T
(n)≥cn
3
,则
T
(n)=
Ω
(n
3
)
如果某种算法在
Ω
(n^
3
)
中,那也一定在
Ω
(n^
2) 中,我们希望找到一个
最“紧”
(即最大)的下限。
4.3 Θ表示法
以上大
O
表示法和大
Ω
表示法是描述某一算法的界限函数。
当界限函数的上、下限相等时
,即如果一种算法既在
O
(
h
(n)) 中,又在Ω
(
h
(n))
中,则用
Θ
表示法,称其为
Θ
(
h
(n))
。
4.3.1 【定义:Θ符号】
假设
f
(
n
)
和
g
(
n
)
是关于整数
n
的非负函数,
f
(
n
)=
Θ
(
g
(
n
))
当且仅当存在正常数
c
1
,
c
2
和某个
n
0
,使得
对于所有的
n
≥
n
0
,有
c
1
g
(
n
) ≤
f
(
n
) ≤
c
2
g
(
n
)
。