算法分析基础---渐进符号和递归式分析

来源:互联网 发布:网络角色游戏排行榜 编辑:程序博客网 时间:2024/05/18 02:48


首先是为什么会使用渐进来分析算法的效率,由于当问题的规模很小的时候,基本上在任何一台机器上都会以很快的速度计算出来,由于算法是机器无关的,编译器无关的,所以只有在问题规模较大的时候分析算法的效率才显得有意义。渐进就是将问题 的规模趋向于无穷大,这样,对于系数,低阶项和常数项都是可以忽略的,因为随着问题规模逐渐趋向于无穷,这些项对于主导项来说,是完全可以忽略的,这样就有了渐进分析算法的五个符号。

基本符号: 

1. 大O符号:用于表示最坏的情况下运行时间,比如冒泡排序算法是O(n^2)就是指的最坏情况下运行时间是O(n^2)

   定义:给定两正值函数和,定义:

,条件为:存在正实数和,使得对于所有的,有

上述的定义表明,当足够大,大过一个特定的时,且存在一个正数,使得不大于,则是的表示。和的关系可以理解为是的一个上界,也可以理解为最终至多增涨的速度与一样快,但不会超过的增涨速度。

 

    2.大Ω符号的定义与O符号的定义类似,但主要区别是,大O符号表示函数在增长到一定程度时总小于一个特定函数的常数倍,大Ω符号则表示总大于。

用数学语言描述即是,若存在使得:

对于所有.

       大O与大Ω关系:大Ω符号与大O符号正好相反,即:。

         大Θ符号是O符号Ω符号的结合。即:若。

          

        剩下的两个符号是:小o和w,这两者是大O和Ω的子集,存在的常数是在所有正常数范围,也就是绝对小于(或者大于),而没有等于。

 

下面是常用的大O符号阶数:

 

符号

名称

常数(阶,下同)

对数

多对数

线性,次线性

迭代对数

线性对数,或对数线性、拟线性、超线性

平方

 

 

多项式,有时叫作“代数”(阶)


指数,有时叫作“几何”(阶)


阶乘,有时叫做“组合”(阶)

 

 

   等式和不等式中出现渐进符号:

           当渐进符号出现在某个公式中时,将其解释为不在乎名称的函数(递归式中将使用),由前面的符号定义可以知道,对于公式n^2 + 2n + 1 也是可以表示成n^2 + Θ(n),换成另外一种函数式写法就是n^2 + f(n),所以前面说解释为不在乎名称的函数,在递归式中使用十分频繁。

递归式的算法分析:

 

    常见的递归式形式  T(n) = aT(n/b) + Θ(n)a > 1,b > 1 T(n)是非负数函数

其中Θ(n)表示问题规模为1的时候开销的代价

 

常见的递归算法分析有以下三种

 

1.代换法

    整体解决思路:a)猜测解的大体形式     b)运用数学归纳法解出有效常数

 

    对于递归式,比如T(n) = 2T(n/)) + n,猜测它为O(n*lgn),然后我们假设在T(n/2) <= c * (n/2)*lg(n / 2),那么证明T(n) <= c * n * lgn有有效常数就可以证明猜测的答案成立。

 

    T(n)<= 2*(c * (n/2) * lg(n/2)) + n = c*n*lgn - cnlg2 + n = cn*lgn - cn + n<= c * n *lgn,这里只是需要c大于等1即可成立,那么有有效数字,说明猜测是成立的。

    当然,如果是n ^2 或者 n^3也是成立的,所以,替换法的准确度并不是一个肯定的结论。对于比较复杂的递归方程式,一般是很难猜得比较近的。在证明过程中,有时会遇到比较复杂的公式,比如带根号的等等,可以运用代换的思想,将变量使用另外的一个简单符号或者形式表示,这样有便于计算。

 

2. 递归树方法

        递归树对于大多数简单的递归式是有效而且形象简单的方法,最好的用法是使用递归树产生好的猜想,再用代换法进行证明。

        在递归树中,每一个节点代表递归树调用集合中一个子问题的代价,将每一层内的代价详解得到每一层代价的集合,再将每层的代价相加得到递归树的所有层次之和的代价,也就是整个递归的代价,递归一般用于分治算法的运行时间分析。

 

        对于递归式T(n) = 3T(n/4) + c*n^2,可以把它分解成一个递归树,如下图。可以看到深度为i的节点,节点总数3^i个,而每个节点(子问题)的大小是n/(4^i),所以每层的总 和是3^i * c* (n/4^i)^2 = (3/16)^i * c*n^2。递归树的深度为log_4(n)(总层数为log_4(n)+1),所以最底层(其深度为log_4(n) )有3^(log_4(n)) = n^log_4(3)个节点,每个节点的代价为T(1),所以最后一层的代价为 n^log_4(3) * T(1),即Ө(n^log_4(3))。

      

下面就是递归树的图像:

 

     对于子问题,其问题规模会越来越小,最终会到达一个边界条件。利用求和公式可以很轻易的算出这个递归式的代价,写出大O的表示,接下来便可以使用代换法进行证明。递归图法解递归式虽然简单形象,但是对于这种完全树是一种很有利的解法,其总代价被均匀的分布到递归树内的每一层上。但是,对于没有这样分布的运用递归树法就显得十分的复杂。

 

3. 主方法、

    主方法(master method)给出了求解如下形式的递归式的公式:
T(n) = a*T(n/b) + f(n) 其中a≥1和b>1是常数,f(n)是一个渐近正的函数。n为非负整数,n/b指floor(n/b)或ceiling(n/b)。那么T(n)可能有如下的渐近界:
   1、若对于某常数ε>0,有f(n) = O(n^(log_b(a)-ε)),则T(n)=Ө(n^(log_b(a)));
   2、若f(n)=Ө(n^(log_b(a))),则T(n) = Ө(n^(log_b(a)) * lgn);
   3、若对某常数ε>0,有f(n)=Ω(n^(log_b(a) + ε)),且对常数c<1与足够大的n,有a*f(n/b) ≤ c*f(n),则T(n) = Ө(f(n))。

 

   对于递归式,主方法给出了一个直接的判断方式,但是一般,我除非是遇到特别复杂的递归式,都会使用递归树和代换法进行分析。相关具体的证明,可以参考《算法导论》-----主定理的证明。

 

   算法的分析在算法设计上面有十分强大的作用,但是结果不一定和实际需求是相吻合的,有时候,算法复杂度高的反而适用,对于系统的研究算法,算法分析是必须有的一课,也许看到这些复杂的符号会让人感觉着急,但是一旦对这些符号运用熟练以后,就会慢慢的感觉到它的优势,正好符合的计算机算法分析的特性,慢慢 的成为算法的衡量手段,所以,学习算法的第一课,学好算法分析。以后将陆续开始算法的学习,希望一起进步,一起学习。

 

参考资料:《离散数学》---集合论   《算法导论》---函数增长,递归式     维基百科---大O符号

 

0 0
原创粉丝点击