1.1算法选用的策略node
1.2问题的规模算法
1.3编写程序的语言数组
1.4编译程序产生的机器代码的质量函数
1.5计算机执行指令的速度post
2.其余影响元素spa
一个特定算法的“运行工做量”的大小,只依赖于问题的规模(一般用整数量n表示),或者说,它是问题规模的函数。3d
假如,随着问题规模 n 的增加,算法执行时间的增加率和 f(n) 的增加率相同,则可记做:T (n) = O(f(n)), 称T (n) 为算法的(渐近)时间复杂度。code
一个算法是由控制结构(顺序、分支和循环3种)和原操做(指固有数据类型的操做)构成的,算法的运行时间取决于二者的综合效果。blog
(Time Complexity)排序
从算法中选取一种对于所研究的问题来讲是基本操做的原操做,以该基本操做 在算法中重复执行的次数 做为算法运行时间的衡量准则。
“基本操做” 指的是,该操做重复执行次数和算法的运行时间成正比。
算法的执行时间=∑原操做(i)的执行次数×原操做(i)的执行时间
详细算法的执行时间与原操做执行次数之和成正比
算法= 控制结构+ 原操做(固有数据类型的操做)
1两个矩阵相乘 eg1:两个矩阵相乘 void mult(inta[], int b[], int&c[] ) { // 以二维数组存储矩阵元素,c为 a 和 b的乘积 for (i=1; i<=n; ++i){ for(j=1; j<=n; ++j) { c[i,j] = 0; for(k=1; k<=n; ++k) c[i,j] += a[i,k]*b[k,j]; } } } 基本操做: 乘法操做时间复杂度: O(n^3)
2选择排序
3起泡排序
4有以下递归函数fact(n),分析其时间复杂度 int fact(int n){ if(n<=1) return(1); (1) else return(n*fact(n-1)); (2) } 解:设fact(n)的运行时间复杂函数是T(n), 该函数中语句(1)的运行时间是O(1), 语句(2)的运行时间为:T(n-1)+O(1), 其中O(1)为基本运算时间, 所以: T(n) = O(1)+T(n-1) = O(1)+O(1)+T(n-2) = …… = (n-1)*O(1)+T(1) = n*O(1) = O(n)则fact(n)的时间复杂度为O(n)。
设n为算法中的问题规模,一般用大O、大Ω和Θ等三种渐进符号表示算法的执行时间与n之间的一种增加关系。
定义1(大O符号),f(n)=O(g(n))(读做“f(n)是g(n)的大O”)当且仅当存在正常量c和n0,使当n≥n0时,f(n)≤cg(n),即g(n)为f(n)的上界。
如3n+2=O(n),由于当n≥2时,3n+2≤4n。
10n2+4n+2=O(n4),由于当n≥2时,10n2+4n+2≤10n4。
大O符号用来描述增加率的上界,表示f(n)的增加最多像g(n) 增加的那样快,也就是说,当输入规模为n时,算法消耗时间的最大值。这个上界的阶越低,结果就越有价值,因此,对于10n2+4n+2,O(n2)比O(n4) 有价值。
一个算法的时间用大O符号表示时,老是采用最有价值的g(n)表示,称之为“紧凑上界”或“紧确上界”。
通常地,若是有
说明:
1.在难以精确计算基本操做执行次数(或语句频度)的状况下,只需求出它关于n的增加率或阶便可2.一个算法的时间复杂度能够具体分为最好、最差(又称最坏)和平均三种状况讨论。
除特别说明外,正常均指最坏状况下的时间复杂度。
1两个矩阵相乘
eg1:两个矩阵相乘
void mult(inta[], int b[], int&c[] ) { // 以二维数组存储矩阵元素,c为 a 和 b的乘积 for (i=1; i<=n; ++i){ for(j=1; j<=n; ++j) { c[i,j] = 0; for(k=1; k<=n; ++k) c[i,j] += a[i,k]*b[k,j]; } } } 基本操做: 乘法操做时间复杂度: O(n^3)
2选择排序
3起泡排序
4有以下递归函数fact(n),分析其时间复杂度
int fact(int n){ if(n<=1) return(1); (1) else return(n*fact(n-1)); (2) } 解:设fact(n)的运行时间复杂函数是T(n), 该函数中语句(1)的运行时间是O(1), 语句(2)的运行时间为:T(n-1)+O(1), 其中O(1)为基本运算时间, 所以: T(n) = O(1)+T(n-1) = O(1)+O(1)+T(n-2) = …… = (n-1)*O(1)+T(1) = n*O(1) = O(n)则fact(n)的时间复杂度为O(n)。
定义2(大Ω符号),f(n)= Ω(g(n))(读做“f(n)是g(n)的大Ω”)当且仅当存在正常量c和nθ,使当n≥n0时,f(n)≥cg(n),即g(n)为f(n)的下界。
如3n+2=Ω(n),由于当n≥1时,3n+2≥3n。
10n2+4n+2=Ω(n2),由于当n≥1时,10n2+4n+2≥n2。
大Ω符号用来描述增加率的下界,表示f(n)的增加最少像g(n) 增加的那样快,也就是说,当输入规模为n时,算法消耗时间的最小值。
与大O符号对称,这个下界的阶越高,结果就越有价值,因此,对于10n2+4n+2,Ω(n2)比Ω(n) 有价值。一个算法的时间用大Ω符号表示时,老是采用最有价值的g(n)表示,称之为“紧凑下界”或“紧确下界”。
通常地,若是,有
。
定义3(大Θ符号),f(n)= Θ(g(n))(读做“f(n)是g(n)的大Θ”)当且仅当存在正常量c一、c2和n0,使当n≥n0时,有c1g(n)≤f(n)≤c2g(n),即g(n)与f(n)的同阶。
如3n+2=Θ (n),10n2+4n+2=Θ(n2)。
通常地,若是,有f(n)=Θ(nm)。
大Θ符号比大O符号和大Ω符号都精确,f(n)=Θ(g(n),当且仅当g(n)既是f(n)的上界又是f(n)的下界。
设一个算法的输入规模为n,Dn是全部输入的集合,任一输入I∈Dn,P(I)是I出现的几率,有ΣP(I) =1,T(I)是算法在输入I下所执行的基本语句次数,则该算法的平均执行时间为:A(n)=。
也就是说算法的平均状况是指用各类特定输入下的基本语句执行次数的带权平均值。
算法的最好状况为:G(n)=,是指算法在全部输入I下所执行基本语句的最少次数。
算法的最坏状况为:W(n)=,是指算法在全部输入I下所执行基本语句的最大次数。
对于非递归算法,分析其时间复杂度相对比较简单,关键是求出表明算法执行时间的表达式。
一般是算法中基本语句的执行次数,是一个关于问题规模n的表达式,而后用渐进符号来表示这个表达式即获得算法的时间复杂度。
【例1.6】给出如下算法的时间复杂度。 void func(int n) { int i=1,k=100; while (i<=n) { k++; i+=2; } } 解:算法中基本语句是while循环内的语句。
设while循环语句执行的次数为m,i从1开始递增,最后取值为1+2m,有: i=1+2m≤n f(n)=m≤(n-1)/2=O(n)。 该算法的时间复杂度为O(n)。
递归算法是采用一种分而治之的方法,把一个“大问题”分解为若干个类似的“小问题”来求解。
对递归算法时间复杂度的分析,关键是根据递归过程创建递推关系式,而后求解这个递推关系式,获得一个表示算法执行时间的表达式,最后用渐进符号来表示这个表达式即获得算法的时间复杂度。
【例1.7】有如下递归算法: void mergesort(int a[],int i,int j) { int m; if (i!=j) { m=(i+j)/2; mergesort(a,i,m); mergesort(a,m+1,j); merge(a,i,j,m); } } 其中,mergesort()用于数组a[0..n-1](设n=2k,这里的k为正整数)的归并排序,
调用该算法的方式为: mergesort(a,0,n-1); 另外merge(a,i,j,m)用于两个有序子序列a[i..j]和a[j+1..m]的有序合并,
是非递归函数,它的时间复杂度为O(n)(这里n=j-i+1)。分析上述调用的时间复杂度。
解:设调用mergesort(a,0,n-1)的执行时间为T(n),
由其执行过程获得如下求执行时间的递归关系(递推关系式):
T(n)=O(1) 当n=1
T(n)=2T(n/2)+O(n) 当n>1
其中,O(n)为merge()所需的时间,设为cn(c为正常量)。所以:
T(n) = 2T(n/2)+cn=2[2T(n/22)+cn/2]+cn=22T(n/22)+2cn
= 23T(n/23)+3cn
= …
= 2kT(n/2k)+kcn
= nO(1)+cnlog2n=n+cnlog2n //这里假设n=2k,则k=log2n
= O(nlog2n)
【例1.8】求解梵塔问题的递归算法以下,分析其时间复杂度。 void Hanoi(int n,char x,char y,char z) { if (n==1) printf("将盘片%d从%c搬到%c\n",n,x,z); else { Hanoi(n-1,x,z,y); printf("将盘片%d从%c搬到%c\n",n,x,z); Hanoi(n-1,y,x,z); } }
解:设调用Hanoi(n,x,y,z)的执行时间为T(n),由其执行过程获得如下求执行时间的递归关系(递推关系式):
T(n)=O(1) 当n=1
T(n)=2T(n-1)+1 当n>1
T(n) = 2[2T(n-2)+1]+1=22T(n-2)+1+21
= 23T(n-3)+1+21+22
= …
= 2n-1T(1)+1+21+22+…+2n-2
= 2n-1 = O(2n)