算法分析
估计算法的时间复杂度
为了简单起见,我们只采用大O的定义:
定义: 如果存在正常数
c
c
c 和
n
0
n_0
n0 使得当
N
⩾
n
0
N\geqslant n_0
N⩾n0 时
T
(
N
)
<
=
c
f
(
N
)
T(N)<=cf(N)
T(N)<=cf(N),则记为
T
(
N
)
=
O
(
f
(
N
)
)
T(N)=O(f(N))
T(N)=O(f(N))
当我们说
T
(
N
)
=
O
(
f
(
N
)
)
T(N)=O(f(N))
T(N)=O(f(N))时,我们是保证函数
T
(
N
)
T(N)
T(N)在以不快于
f
(
N
)
f(N)
f(N)的速度增长,因此,
f
(
N
)
f(N)
f(N)是
T
(
N
)
T(N)
T(N)的一个上界。
对于一个具体的程序,我们通常希望知道它的时间复杂度和空间复杂度(这个我们放到以后再说),这就是我们要做的算法分析,我们看一个简单的例子:
int Sum(int N){
int i,sum=0;
for(i = 1;i <= N;i++ ){
sum += i;
}
return sum;
}
假设 sum+=i 这个操作需要耗费1个时间单元,它被执行了N次。初始化 i 和 sum 各需要1个时间单元,返回值也需要1个,那么这段程序的开销就是N+3。我们会说这段程序的时间复杂度是 O ( N ) O(N) O(N)。
简单计算时间复杂度的方法
最简单的,我们只需要数出循环的开销就可以了。
循环嵌套则将其开销相乘。
递归的程序则判断递归的总空间(例如归并排序,快速排序,回溯法)。
我们不关心常数和增长率较小的函数,我们只关心最大的,增长最快的函数。
常见的时间复杂度函数(由“小”到“大”):
函数 | 名称 |
---|---|
c | 常数 |
l o g N logN logN | 对数级 |
l o g 2 N log^2N log2N | 对数平方 |
N N N | 线性 |
N l o g N NlogN NlogN | |
N 2 N^2 N2 | 平方级 |
N 3 N^3 N3 | 立方级 |
2 N 2^N 2N | 指数级 |
参考资料:
Data Structures and Algorithm Analysis in C – Mark Allen Weiss