数据结构第一章
1.1 基本概念
数据——计算机程序加工的原料
数据元素——数据的基本单位
数据项——不可分割的最小单位
数据对象——数据的一个子集
- 数据类型
- 原子类型
- 结构类型
- 抽象数据类型(ADT)——可以定义一个完整的数据结构
- 数据结构——相互之间存在一种或多种特定关系的数据元素的集合
- 逻辑结构
- 线性结构:一对一(线性表、栈、队列、串、数组、广义表)
- 非线性结构(树、图、集合)
- 集合:同属于一个集合
- 树形结构:一对多
- 图/网状结构:多对多(有向图、无向图)
- 存储结构(物理结构)
- 顺序存储
- 优点:可实现随机存取
- 缺点:只能使用相邻的一整块存储单元
- 链式存储
- 优点:不会出现碎片现象,能充分利用所有存储单元
- 缺点:指针占用额外存储空间,只能顺序存取
- 索引存储
- 优点:检索速度快
- 缺点:附加索引表,占用额外空间
- 散列存储(哈希存储)
- 优点:检索,增加,删除很快
- 缺点:会产生冲突,解决冲突会增加时间,空间开销
- 顺序存储
- 数据的运算
- 运算的定义:针对逻辑结构,指出运算功能
- 运算的实现:针对存储结构,指出运算的具体操作步骤
- 逻辑结构
-
数据的逻辑结构独立于其存储结构
-
链式存储设计时,结点内的单元地址(一个结点内部,值域与指针域)一定连续
-
两种不同的数据结构,他们的逻辑结构和物理结构完全有可能相同(二叉树与二叉排序树)
-
对相同的逻辑结构,同一种运算在不同的方式存储方式下实现时,其运算速率不同(线性表的顺序与链式)
-
ADT:描述了数据的逻辑结构和抽象运算,通常用(数据对象,数据关系,基本操作集)这样的三元组来表示,从而构成一个完整的数据结构定义.
1.2 算法简述
算法:对特定问题求解步骤的秒数
-
算法五大特性
- 有穷性:执行有穷步结束,每一步在有穷时间内完成
- 确定性:每条指令有确切定义,相同输入只能得出相同输出
- 可行性:执行有限次实现
- 输入:一个算法有零个或多个输入
- 输出:一个算法有一个活多个输出
-
好算法的几大要求
- 正确性
- 可读性
- 健壮性:对输入的非法数据进行反应或处理
- 效率与低存储量需求
1.2.1 时间复杂度
算法的时间复杂度不仅依赖于问题的规模n,也取决于待输入数据的性质(如:输入的数据元素的初始状态)
加法规则:T(n) = o(f(n)) + O(g(n)) = o(max(f(n),g(n)))
乘法规则:T(n) = O(f(n)) x O(g(n)) = O(f(n) x g(n))
常见的渐进时间复杂度:O(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^k) < O(2^n) < O(n!) < O(n^n)
时间复杂度常用的记法:
1. 访问数组中的元素——`O(1)`
2. 算法中每个步骤去掉一半数据元素,如二分检索——`O(logn)`
3. 用strcmp比较两个具有n个字符的串——`O(n)`
4. 常规的矩阵乘算法——`O(n^3)`
5. 指数时间算法通常来源于需要求出所有可能结果
例:
i=1; /* 1 */
while(i<n)
i = i*2; /* 2 */
解:
语句1频度是1,
设语句2频度是f(n)
则2^f(n) <= n ==> f(n) <= logn
取最大值f(n) = logn
所以
T(n) = O(logn)
int fact(int n){
if(n<1)
return 1;
return n * fact(n-1);
}
/* 递归算法(整数n的阶乘)时间复杂度为:O(n) */
count = 0;
for(k=1;k<=n;k*=2)
for(j=1;j<=n;j++)
count++;
/* T(n) = O(nlogn) */
- 在相同规模n下,复杂度为O(n)的算法在时间上总是优于复杂度为O(2^n)的算法
- 所谓时间复杂度,是指最坏情况下估算算法执行时间的一个上界
- 同一个算法,实现语言的级别越高,执行效率越低 ----严蔚敏教材原话
归纳:时间复杂度的两类题型
- 循环主体中的变量参与循环条件的判断——此类题应该找出主体语句中与T(n)成正比的循环变量
- 循环主体中的变量与循环条件无关——采用数学归纳法或直接累计循环次数,多层循环时从内到外分析
- 递归程序一般使用公式进行递推
- 非递归程序直接累计次数
1.2.2 空间复杂度
算法的空间复杂度S(n)定义为该算法所耗费的存储空间
算法原地工作:算法所需的辅助空间为常量,即O(1)