程序性能
算法分析
计算机算法是指解决问题的步骤,应该具有可执行性,确定性,有穷性三个特点。
设计一个“好的”算法,应该达到的目标是健壮的, 无二义性的。
ps:健壮的是指当输入出现非法错误时,算法会进行合适的处理,而不是产生难以理解的输出结果
算法分析的方法有解析方法和实验测量方法,从解析的角度又分为时间复杂度分析和空间复杂度分析。
程序性能
空间复杂度
空间复杂度是指程序运行所需的内存大小
程序员对空间复杂度感兴趣的原因:
①在任何一个计算机上运行程序,需要保证有足够的内存能用
②不同的解决方案对内存可能有不同的要求,一般希望选择更优的方案,把更多的内存留作他用
③通过对空间复杂度的分析,可以对问题的规模进行一个大致的估计
时间复杂度
时间复杂度是指程序运行所需要的时间
一个程序的时间复杂度取决与问题的规模(n)和待处理数据的初态
程序员对时间复杂度感兴趣的原因:
①为避免过长的等待而造成损失,根据具体问题会对程序有一个运行时间上限的要求
②与用户进行交互的程序需要一个令人满意的实时响应
③同样的,对于不同的解决方案一般选择更优的方案
空间复杂度
程序所需空间组成
指令空间(instruction space)
编译之后程序指令所需的空间
大小和编译器有关,相同编译器对相同程序的编译结果也可能不同
数据空间(data space)
所有常量和变量所需要的存储空间,分两部分
常量和简单变量
动态数组和动态类实例等动态对象(复杂的变量, composite variables)
环境栈空间(environment stack space)
函数被调用的时候,函数的返回地址(端断口地址)和当前函数的所有局部变量和形式参数都被保存到环境栈中
空间复杂度分析
上面说的是一个程序运行所需要的空间
那和特征实例相关的部分
只包括复杂变量的数据空间和递归函数的环境栈空间
因此,一个程序运行所需要的空间大致可以分为固定部分和可变部分,其中可变部分主要依赖于实例特征(feature of instance):
S( p ) = Sp(feature) + constant
时间复杂度
①找到算法的基本语句(执行次数最多的语句),通常是最内层循环体
②计算基本语句执行次数的数量级(以最高次的为主)
③用渐进记号表示时间复杂度
ps:语句的执行次数成为语句频度或者执行频度,记为T(n)
渐进记法(approximate notations)
1.O记法
f(n) = O(g(n))表示函数f(n)的增长不会快于(渐近小于等于)函数g(n)
习惯上g(n)是满足上式的最小单位项(系数为1),例如O(3n2+6n+9) = O(n2),其中"="读作“是”
2.Ω记法
f(n) = Ω(g(n))表示函数f(n)的增长不会慢于(渐近大于等于)函数g(n)
3.θ记法
f(n) = θ(g(n))表示函数f(n)的增长渐近等于函数g(n)
时间复杂度分析
时间复杂度分析是一种事前分析估算的方法
常见的时间复杂度
由小到大:
O(1) < O(lg n) < O(n) < O(nlg n) < O(n2) < O(n3) < … <O(2n) < O(n!)
Best Case:
Worst Case:
Average Case:
常见算法的时间复杂度分析
渐近时间复杂度的分析方法
计步法
代入法
例1:
观察问题规模的特点,我们不妨假设2k < n ≦ 2k+1,因此有2k-1 < n/2 ≦ 2k
n = 1时成立
设当n < n0时都成立,则有T(n) ≦ cn
⌈
\lceil
⌈ log2n
⌉
\rceil
⌉
将T(
⌊
n
/
2
⌋
\lfloor n/2 \rfloor
⌊n/2⌋) 和 T(
⌈
n
/
2
⌉
\lceil n/2 \rceil
⌈n/2⌉)带入
T(n)
≤
\leq
≤ cn×k + cn/2
≤
\leq
≤ cn×k + cn = cn
⌈
l
o
g
2
n
⌉
\lceil log~2~n \rceil
⌈log 2 n⌉
例2:
根据递推式我们可以得出T(n)的渐近时间为O(n2),因此我们可以据此作出假设,令T(n)
≤
\leq
≤ c1n2 - c2n,c1,c2为待定常数,随后的证明就简单了
递归树
1.极端情况:T(n) = T(0) + T(n - 1) + cn
做渐近分析时,将递推式展开,T(n) = nT(0) + c[1 + 2 + … + (n - 1) + n] = O(n2)
递归树如下所示:树的深度h = n
2.一般情况:T(n) = T(αn) + T(βn) + θ(n)
这样问题的时间复杂度一般是O(nlg n)
在递归树的表示中很容易看出,这里也可以计算得到
左边子树的最大深度为 log1/αn,右边子树的最大深度为 log1/βn
因此T(n)的渐近值 cnlog1/αn
≤
\leq
≤ T(n)
≤
\leq
≤ cnlog1/βn
下图以T(n) = T(0.1n) + T(0.9n) + θ(n)为例:
Master Method
分治算法中常要用到递归方法来处理其中的问题
分支策略三步走:分解, 解决,合并
主方法表现形式:
T(n) = aT(n/b) + f(n) , a > 1, b > 1
n:问题规模
a:子问题数量
n/b:子问题规模
①若存在ε满足,f(n) = O(
n
l
o
g
b
a
−
ε
n^{log_{b}a-ε}
nlogba−ε),则T(n) = θ(
n
l
o
g
b
a
n^{log_{b}a}
nlogba)
②若f(n) = O(
n
l
o
g
b
a
n^{log_{b}a}
nlogba),则T(n) = θ(
n
l
o
g
b
a
l
g
n
n^{log_{b}a} lgn
nlogbalgn)
③若存在ε满足,f(n) = O(
n
l
o
g
b
a
+
ε
n^{log_{b}a+ε}
nlogba+ε),则T(n) = θ(f(n))
例:
①对于递推式T(n) = 9T(n/3) + n
则有a = 9, b = 3, f(n) = n
当ε = 1时,有
n
l
o
g
b
a
−
ε
n^{log_{b}a-ε}
nlogba−ε =
n
l
o
g
3
9
−
1
n^{log_{3}9-1}
nlog39−1 = n = f(n)
因此,T(n) = θ(
n
2
n^2
n2)
②对于递推式T(n) = T(2n/3) + 1
则有a = 1, b = 2/3, f(n) = 1
有f(n) = O(
n
l
o
g
b
a
n^{log_{b}a}
nlogba) = O(1)
因此, T(n) = θ(lgn)
③对于递推式T(n) = 3T(n/4) + nlg n
T(n) = O(nlg n)