数据
数据的概念
数据是信息的载体,是描述客观事物的数、字符和能输入到计算机并被计算机程序识别和处理的符号的集合。数据是计算机程序加工的原料。
数据元素、数据项
数据元素是数据的基本单位,通常可以作为一个整体来进行考录和处理。
一个数据元素可以由若干个数据项组成,数据项是构成数据元素的不可分割的最小单位。
数据对象、数据结构
数据对象是具有相同性质的数据元素的集合,是数据的一个子集。
数据结构是互相之间存在一种或多种特定关系的数据元素的集合
形式定义:数据结构是一个二元组 Data_Structure =(D,R),其中,D是数据元素的有限集,R是D上关系的有限集。
数据结构的三要素
数据结构的三要素包含逻辑结构、数据的运算、物理结构(存储结构)
逻辑结构
数据的逻辑结构是本质,可以分为:线性结构和非线性结构。
集合结构
各个元素同属于一个集合,别无其他的关系。
线性结构
数据元素之间是一对一的关系,除了第一个元素,所有元素都有唯一的前驱。除了最后一个元素,所有元素都有唯一的后继。
树形结构
数据元素是一对多的关系
图结构
数据元素之间是多对多的关系。
逻辑结构是数据组织的“本质性”的东西:
(1)逻辑结构与数据元素本身的形式、内容无关。
(2)逻辑结构与数据元素的相对位置无关。
(3)逻辑结构与所含数据元素的个数无关。
算法的设计取决于选定的逻辑结构,而算法的实现依赖于采用的存储结构
数据的运算
针对于某种逻辑结构,结合实际的需求,定义基本运算。
数据的运算和逻辑结构共同定义了一种数据结构。
物理结构
如何用计算机表示数据之间的逻辑关系
顺序存储
把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。
链式存储
逻辑上相邻的元素在物理位置上可以不相邻,借助元素的存储地址的指针来表示元素之间的逻辑关系。
索引存储
在存储信息的同时,还建立附加的索引表,索引表中的每项成为索引项,索引项的形式一般是(关键字,地址)
散列存储
根据元素的关键字,直接计算出元素的存储地址,又称为哈希(Hash)存储。
顺序存储与非顺序存储
链式存储、索引存储、散列存储都是非顺序存储。
1、若采用顺序存储,各个数据元素在物理上必须是连续的;若采用非顺序存储,各个数据元素在物理上是可以离散的。
2、数据的存储结构会影响存储空间分配的方便程度
3、数据的存储结构会影响对数据运算的速度
抽象数据类型
数据类型
数据对象集合以及与其相关联的操作集;是对数据的取值范围,数据元素之间的结构以及允许施加操作的一种总体描述。分为:
简单类型:(原子类型)
结构类型:有简单的数据类型按照一定的规则构造而成,如数组等。
抽象:描述数据的方法不依赖具体的实现,与存放数据的机器无关,与数据存储的物理结构无关,与实现操作的算法和编程语言均无关。
抽象数据类型
抽象数据类型:(Abstract Data Type)ADT:一个数学模型以及定义在该模型上的一组操作。抽象数据类型的定义取决于它的一组逻辑特性,而与其在计算机内部如何表示和实现无关。即不论其内部结构如何变化,只要它的数学特性不变,都不影响其外部的使用。
抽象数据类型的定义格式:
ADT 抽象数据类型名{
数据对象:{数据对象定义}
数据关系:{数据关系定义}
基本操作:{基本操作定义}
}ADT 抽象数据类型名
算法基本概念
程序=数据结构+算法
算法是对特定问题求解步骤的一种描述,它是指令的有限序列,其中的每一条指令代表一个或多个操作。
算法的特性
有穷性
一个算法必须在执行又穷步骤之后结束,且每一步都在有穷的时间内完成。
注:算法必须是有穷的,而程序可以使无穷的。
确定性
算法中的每一条指令都必须有确切的含义,对于相同的输入只能得到相同的输出。
可行性
算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现。
输入
一个算法有零个或者多个输入,这些输入取之于某个特定对象的集合。
输出
一个算法有零个或者多个输出,这些输出与输入有着某种特定关系的量。
好算法的特质
正确性
算法可以正确的解决求解问题
可读性
算法应具有良好的可读性,帮助人们理解
健壮性
输入非法数据时,算法可以适当的做出反应或者进行处理,不会产生莫名其妙的输出。
高效率和低存储量
花费的时间少,时间复杂度低
不费内存,空间复杂度低
算法效率的度量
时间复杂度
评估时间开销
算法先运行,事后统计运行时间
存在问题:
1、与机器性能有关
2、与编程语言有关,越高级的的语言执行效率越低
3、编译程序产生的机器指令的质量有关
4、有些算法不可以事后统计,如导弹控制算法
算法的时间复杂度
事前预估算法的时间开销T(n)与问题规模n的关系
大O表示“同阶”,同等数量级。
上式可简化为:
加法规则:
乘法规则:
时间复杂度阶数比较:
顺序执行的代码只会影响常数项可以忽略。
只需挑选循环中的一个基本操作分析他的执行次数与n的关系即可。
如果有多层嵌套循环,只需关注最深层循环循环了几次。
平均时间复杂度
最坏时间复杂度:最坏的情况下算法的时间复杂度
平均时间复杂度:所有输入示例等概率出现的情况下,算法的期望运行时间。
最好时间复杂度:最好情况下算法的时间复杂度。
空间复杂度
空间开销与问题规模n之间的关系
void loveYou(int n){
int i=1;
while(i<=n){
i++;
printf("I love you %d\n",i);
}
print ("I love you more than %d\n",n);
}
无论问题的规模如何变化,运算运行所需的内存空间都是固定的常量,算法的空间复杂度为:
S(n)=O(1)
算法原地工作,所需的内存空间是常量。
void test(int n){
int flag[n];
int i;
}
假设一个 int 变量占4B
所需的内存空间为:4n+8
S(n)=O(n)
void test(int n){
int flag[n][n];
int i;
}
S(n)=O(n²)
void loveYou(int n){
int a,b,c;
if(n>1){
loveyou(n-1);
}
printf("I love you %d\n",n);
}
int main(){
loveYou(5);
}
S(n)=O(n) 空间复杂度=递归调用的深度
void loveYou(int n){
int flag[n];
if(n>1){
loveyou(n-1);
}
printf("I love you %d\n",n);
}
int main(){
loveYou(5);
}
S(n)=O(n²)