算法的渐近分析

有了算法的具体语句后,我们可以根据语句情况、编程语言、编译器等外部条件的情况算出一个算法的准确时间复杂度,通常这种精确的时间复杂度由于考虑的因素较多,因此表达式比较复杂(如:T(n) = 168n^3+65n^2+n+10000),当外部条件改变时,如实现语言变化、执行算法的计算机不同等,式子中的常量系数也会发生变化。因此,即使是同一个算法,在不同条件时精确的时间复杂度也会不同,这就给衡量不同算法的优劣带来了不便。

如果能抛开外界因素,还可以在一定程度上能够比较出两个算法的优劣,这就是渐近分析能够带给工程师的礼物。首先根据数学原理,当一个函数(如前边的T(n))的n变得非常大以至于趋于无穷时,函数值的大小主要是由函数的最高阶项来决定的。这有点像比较两个汽车谁能跑的更快,纵然车身轻重、轮胎情况、四驱还是两驱等情况都是考虑因素,但是决定性因素还是汽车的发动机情况。因此,当处理的问题的数据量很大的时候,我们可以只考虑该算法时间度表达式中最高阶的项,抓住主要矛盾来处理问题,这就是算法渐近分析的基本思想。何况当今计算机处理的数据量越来越大,因此算法的渐近分析更是可以派上用场。

通俗来讲,算法的渐近复杂度就是忽略掉低阶项以及常数系数(常数是指数的除外,如n^2n,这里的2就不能忽略)来比较最高阶的项。如果从严格的数学定义出发,则需要引入三个符号:O、θ、Ω

O(f(n))表示一个函数集合,这个集合中的所有函数T(n)满足:存在一个正数c,以及N,当n >= N时,T(n) <= cf(n)。

Ω(f(n))表示一个函数集合,这个集合中的所有函数T(n)满足:存在一个正数d,以及N,当n >= N时,T(n) >= df(n)。

当T(n)既满足O又满足Ω时,T(n) = Θ(n)。

算法的渐近分析的意义除了可以忽略掉低阶和常数系数因素外,它也给了我们一个在更宏观的角度去看到算法的复杂度,例如T(n) = n^2与T(n) = 1.1n^2 + (x^1.9 + 10)sin(10x+1.5)+30,在微观和宏观下观察两个算法复杂度如图:

由图可以看出,在微观下两个函数的复杂度表现差异较大,而当把度量单位放大时,两个函数的时间复杂度基本相似了。
明白了渐近分析的概念以及意义,下面可以对不同复杂度的算法进行比较了,下面是一个常见复杂度的递增排序表:


在O(nlogn)之前的(包括O(nlogn))的算法通常被认为是高效的算法, O(n^7)或更慢的算法通常认为是无用的算法,在它们之间的要视输入问题规模以及隐藏的常数变量而定是否有用。

算法渐近分析需要注意的两点:

* 当省略常数系数时,如果系数在指数上绝不能省略。

* 由于渐近分析隐藏了常数,因此在实际的工程中不能充分的反映客观情况,如U(n) = 100n与T(n) = nlog2n,按照渐近分析,U(n)的复杂度要优于T(n),然而在实际中,只有当你的输入规模大于宇宙原子总数的时候,这种情况才成立,因为log2n在能遇见的输入量的时候基本是小于50的。




展开阅读全文

没有更多推荐了,返回首页