1.数据结构
1.1 基本概念:
- 数据元素:也称为记录,是数据的基本单位。比如把动物看作数据,那么数据元素指的就是牛、羊、马等。
- 数据项:这是数据的最小单位,多个数据项构成了一个数据元素。比如把牛看作数据元素,那么数据项指的就是牛的年龄、体态等。
- 数据对象:这是数据的子集,表示性质相同的数据元素的集合。所谓性质相同,指的是各数据元素之间有相同数目和类型的数据项。
- 数据结构:是相互之间存在一种或多种特定关系的数据元素的集合。结构,指的就是这些元素互相之间的关系,这是重点。
1.2 分类:
- 逻辑结构(思路):
从广义上分为线性结构和非线性结构。- 非线性结构:集合(同在一块)、树(一对多)、图(多对多);
- 线性结构:表、栈、队列、串、数组
- 物理/存储结构(实现):
- 顺序存储结构
- 链接存储结构
- 索引存储结构
- 散列存储结构
1.3 抽象数据类型 ADT
ADT 即 Abstract data type,抽象数据类型的三个主体是数据对象 + 关系 + 操作。
我们可以用下面的格式描述抽象数据类型:
ADT 抽象数据类型名{
数据对象:it is.....
数据关系:they are.....
基本操作:
操作1:done sth....
初始条件:....
操作结果:....
操作2:done sth....
初始条件:....
操作结果:....
} ADT 抽象数据类型名
2.算法
2.1 基本特性:
有穷性(时间有穷、步骤有穷)、确定性(没有歧义)、可行性、输入、输出
2.2 优劣标准:
正确性(至少可以得到正确结果,对于非法输入也应有提示)、可读性、健壮性、高效性(时间 + 空间)
2.3 时间复杂度
- 一个算法的执行总时间应该等于每条语句执行时间之和,假定执行时间都为单位 1,那么则等于语句总数,同时我们只考虑耗时长的操作语句 —— 即基本操作语句,那么基本操作语句的执行次数(语句频度)就可以在某种关系上反映算法的执行总时间。
- 大 O 表示法:
给定问题规模 n 以及关于 n 的函数 f(n),其中,f(n) 代表基本语句执行次数。那么,时间复杂度T(n) = O(f(n))
,它表示随问题规模 n 的增大,算法执行时间的增长率和 f(n) 的增长率相同。 - 大 O 阶推导(分析时间复杂度):
- 找出语句频度最高的基本语句;
- 基于该语句的频度推导出对应的 f(n);
- 取 f(n) 的数量级得到最终的 f(n)。这意味着允许我们忽略低次幂和最高次幂的系数。
- 经过大 O 阶推导,可以得到常数阶、平方阶、对数阶等。需要注意的是,当算法可以在常数时间内完成时(与问题规模无关),其时间复杂度依然是常数阶 O(1)。
2.4 空间复杂度
空间复杂度
S(n)=O(f(n))
,其中,n 为问题规模,f(n) 表示关于 n 所占存储空间的函数。若算法执行时所需的辅助空间相对于问题规模来说是一个常数,则称此算法为原地工作,空间复杂度为 O(1)。也就是说,不管我问题规模多大,所需要的辅助空间始终是固定的。比如下面两个算法:
//算法1
for(i = 0;i < n/2;i++){
t = a[i];
a[i] = a[n-i-1];
a[n-i-1] = t;
}
//算法2
for(i = 0;i < n;i++)
b[i] = a[n-i-1];
for(i = 0;i < n;i++)
a[i] = b[i];
对于算法1,不管问题规模多大,总是只需要一个临时变量 t 暂存值即可,因此其空间复杂度为 O(1);对于算法2,采用的是逆序输出原数组到新数组中,之后再覆盖原数组,很显然,随着 n 的增大,新数组要求的存储空间也要增大,所以其空间复杂度为 O(n)。