这是我第一次写博,由于最近在看算法方面的书,就从这个方面说起吧。
1. O记号
一般我们要分析一个算法,不可避免的要提到记号O,例如我们说一个算法的复杂度T(n) = O(n2).表示的是这个算法在最坏的情况下,其运行的时间T(n)与输入的长度(n)存在一个渐进上界cn2(c是一个正常数),用数学语言就是:
存在这一个正常数c,正整数n0,使得对于所有的n>=n0,都有 T(n) <= cn2。
从这个式子我们可以看出,在分析一个算法复杂度的时候,我们只关心:
(1) n足够大的情况。
(2) 只考虑随着n的增大,运行时间增加的数量级(是n的几次方),而忽略其系数(c)。
其实,在一般的算法书中还存在这 两个符号Ώ和Θ,T(n) = Ώ(n2),表示最坏情况的下界,即:
存在这一个正常数c,正整数n0,使得对于所有的n>=n0,都有 T(n) >= cn2。如果T(n) 即等于O(n2)又等于Ώ(n2),我们说T(n) = Θ(n2)。
2. 排序问题
这个地球人都知道,最简单的情况就是:
给定一个整数数组A[n],将其中的元素进行非降序排列,并输出出来。
3. Insert排序算法
Insert排序算法的原理有点象我们打牌的时候的齐牌,所有的牌都覆盖在桌上,一张一张的拿起,拿到第一张我们认为它最小,然后拿第二张,将它插到前面排好的序列(其实只有一张)中去,这样前两张排好了,同理,拿到第三张时,将其插到前面排好的序列中去,依此类推,直到将所有的牌都排好了为止。
代码如下:
那么我们如何分析Insert算法的复杂度呢,上面代码的操作主要时比较(==,>,<,>=,<=)和交换(赋值=)组成。假定一次比较操作的时间相当,为a,一次赋值的时间也相当,为 b,那么上面算法的最坏情况的时间为:
T(N) = (a+2b) *(N-1) + (a+b)*(1+2+3+...+N-1) = (a+2b) *(N-1) + (a+b)* (N-1)*(N-2) /2 = O(N2)
4. Merge排序算法
Merge算法是一种分治思想,将N个元素的排序分成N/2个元素的子问题,然后将排好的子序列进行合并。
代码如下:
根据上面的代码,我们可以很容易的知道函数Merge的复杂度为Θ(N),那么MergeSort需要的时间为:
T(N)= 2T(N/2)+ Θ(N).
那么根据上式我们怎么得到MergeSort的复杂度呢?
5. 主定理
主定理(不知道为什么叫做主定理)就是为了解决上述问题的。描述如下:
设 a >=1和 b >=1 为常数,f(n)为一函数,T(n) =aT(n/b) + f(n),如果
n/b 不为整数的话,可为比n/b小的最大整数,或者比n/b大的最小整数,则有:
1. 若对某常数 e>0, 有f(n) = O(nlogba-e). 则 T(n) = Θ(nlogba).
2. 若f(n) = Θ(nlogba),则 T(n) = Θ(nlogbalgn).
3. 若对某常数 e>0,有f(n) = Ώ(nlogba+e), 且对常量c<1与所有足够大的n,有af(n/b) <=cf(n),则:
T(n) = Θ(f(n)).
根据如上的定理,T(N)=2T(N/2+Θ(N)属于第二种情况,即有T(n) = Θ(nlogbalgn) = Θ(nlgn) = O(nlgn)。
从上面的分析来看,在时间上Merge算法要由于Insert算法。