范文一:算法复杂度计算
算法复杂度计算
算法复杂度是在《数据结构》这门课程的第一章里出现的,因为它稍微涉及到一些数学问题,所以很多同学感觉很难,加上这个概念也不是那么具体,更让许多同学学起来无从下手,下面我们就这个问题给各位考生进行分析。
首先了解一下几个概念。一个是时间复杂度,一个是渐近时间复杂度。前者是某个算法的时间耗费,它是该算法所求解问题规模n的函数,而后者是指当问题规模趋向无穷大时,该算法时间复杂度的数量级。 当我们评价一个算法的时间性能时,主要标准就是算法的渐近时间复杂度,因此,在算法分析时,往往对两者不予区分,经常是将渐近时间复杂度T(n)=O(f(n))简称为时间复杂度,其中的f(n)一般是算法中频度最大的语句频度。
此外,算法中语句的频度不仅与问题规模有关,还与输入实例中各元素的取值相关。但是我们总是考虑在最坏的情况下的时间复杂度。以保证算法的运行时间不会比它更长。
常见的时间复杂度,按数量级递增排列依次为:常数阶O(1){Hash表的查找}、对数阶O(log2n){二分查找}、线性阶O(n)、线性对数阶O(nlog2n){快速排序的平均复杂度}、平方阶O(n^2){冒泡排序}、立方阶O(n^3){求最短路径的Floyd算法}、k次方阶O(n^k)、指数阶O(2^n){汉诺塔}。
下面我们通过例子加以说明,让大家碰到问题时知道如何去解决。
1、设三个函数f,g,h分别为 f(n)=100n^3+n^2+1000 , g(n)=25n^3+5000n^2 , h(n)=n^1.5+5000nlgn
请判断下列关系是否成立:
(1) f(n)=O(g(n))
(2) g(n)=O(f(n))
(3) h(n)=O(n^1.5)
(4) h(n)=O(nlgn)
这里我们复习一下渐近时间复杂度的表示法T(n)=O(f(n)),这里的"O"是数学符号,它的严格定义是"若T(n)和f(n)是定义在正整数集合上的 两个函数,则T(n)=O(f(n))表示存在正的常数C和n0 ,使得当n?n0时都满足0?T(n)?C?f(n)。"用容易理解的话说就是这两个函数当整型自变量n趋向于无穷大时,两者的比值是一个不等于0的常 数。这么一来,就好计算了吧。
(1)成立。题中由于两个函数的最高次项都是n^3,因此当n??时,两个函数的比值是一个常数,所以这个关系式是成立的。
(2)成立。与上同理。
(3)成立。与上同理。
(4)不成立。由于当n??时n^1.5比nlgn递增的快,所以h(n)与nlgn的比值不是常数,故不成立。 2、设n为正整数,利用大"O"记号,将下列程序段的执行时间表示为n的函数。
(1) i=1; k=0
while(i
{ k=k+10*i;i++;
}
解答:T(n)=n-1, T(n)=O(n), 这个函数是按线性阶递增的。
(2) x=n; // n>1
while (x>=(y+1)*(y+1))
y++;
解答:T(n)=n1/2 ,T(n)=O(n1/2), 最坏的情况是y=0,那么循环的次数是n1/2次,这是一个按平方根阶递增的函数。
(3) x=91; y=100;
算法复杂度计算
while(y>0)
if(x>100)
{x=x-10;y--;}
else x++;
解答: T(n)=O(1), 这个程序看起来有点吓人,总共循环运行了1000次,但是我们看到n没有? 没。这段程序的运行是和n无关的,就算它再循环一万年,我们也不管他,只是一个常数阶的函数。
规则:有如下复杂度关系
c < log2n="">< n="">< n="" *="" log2n="">< n^2="">< n^3="">< 2^n="">< 3^n="">< n!="" 其中c是一个常量,如果一个算法的复杂度为c="" 、="" log2n="" 、n="" 、="" n*log2n="" ,那么这个算法时间效率比较高="" ,如果是="" 2^n="" ,="" 3^n="" ,n!,那么稍微大一些的n就会令这个算法不能动了,居于中间的几个则差强人意。="" 我们常需要描述特定算法相对于="" n(输入元素的个数="" )需要做的工作量。在一组未排序的数据中检索,所需的时间与="" n成正比;如果是对排序数据用二分检索,花费的时间正比于logn。排序时间可能正比于n^2或者nlogn。="" 我们希望能够比较算法的运行时间和空间要求,并使这种比较能与程序设计语言、编译系统、机器结构、处理器的速度及系统的负载等复杂因素无关。="">
为了这个目的,人们提出了一种标准的记法,称为“大O记法”.在这种描述中使用的基本参数是 n,即问题实例的规模,把复杂性或运行时间表达为n的函数 。这里的“O”表示量级 (order),比如说“二分检索是 O(logn)的”,也就是说它需要“通过logn量级的步骤去检索一个规模为n的数组”记法O ( f(n) )表示当n增大时,运行时间至多将以正比于f(n)的速度增长。这种渐进估计对算法的理论分析和大致比较是非常有价值的,但在实践中细节也可能造成差异。例如,一个低附加代价的O(n2)算法在n较小的情况下可能比一个高附加代价的O(nlogn)算法运行得更快。当然,随着n足够大以后,具有较慢上升函数的算法必然工作得更快。 Temp=i;i=j;j=temp; 以上三条单个语句的频度均为1,该程序段的执行时间是一个与问题规模n无关的常数。
算法的时间复杂度为常数阶,记作T(n)=O(1)。如果算法的执行时 间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。
例 2.1. 交换i和j的内容
1) sum=0; (一次)
2) for(i=1;i<=n;i++) (n次="" )="">=n;i++)>
3) for(j=1;j<=n;j++) (n^2次="" )="">=n;j++)>
4) sum++; (n^2次 )
解:T(n)=2n^2+n+1 =O(n^2)
例 2.2.
for (i=1;i
f(n)=2n^2-n-1+(n-1)=2n^2-2,该程序的时间复杂度T(n)=O(n^2).
例 2.3.
算法复杂度计算
a=0;b=1; ?
for (i=1;i<=n;i++)>=n;i++)>
...{
s=a+b; ?
b=a; ?
a=s; ?
}
解:语句1的频度:2, 语句2的频度: n, 语句3的频度: n-1, 语句4的频度:n-1,
语句5的频度:n-1, 则:T(n)=2+n+3(n-1)=4n-1=O(n).
例 2.4.
i=1; ?
while (i<=n)>=n)>
i=i*2; ?
解:语句1的频度是1, 设语句2的频度是f(n), 则:2^f(n)<><=log2n 取最大值f(n)="log2n,则该程序的时间复杂度T(n)=O(log2n" )="">=log2n>
例 2.5.
for(i=0;i
次所以,i从0取到n, 则循环共进行了: 0+(1-1)*1/2+...+(n-1)n/2=n(n+1)(n-1)/6所以时间复杂度为O(n^3).我们还应该区分算法的最坏情况的行为和期望行为。如快速排序的最坏情况运行时间是O(n^2),但期望时间是O(nlogn)。通过每次都仔细地选择基准值,我们有可能把平方情况 (即O(n^2)情况)的概率减小到几乎等于0。在实际中,精心实现的快速排序一般都能以(O(nlogn)时间运行。
下面是一些常用的记法:
访问数组中的元素是常数时间操作,或说O(1)操作。一个算法如果能在每个步骤去掉一半数据元素,如二分检索,通常它就取O(logn)时间。用strcmp比较两个具有n个字符的串需要O(n)时间 。常规的矩阵乘算法是O(n^3),因为算出每个元素都需要将n对元素相乘并加到一起,所有元素的个数是n^2。 指数时间算法通常来源于需要求出所有可能结果。例如,n个元 素的集合共有2n个子集,所以要求出所有子集的算法将是O(2n)的。指数算法一般说来是太复杂了,除非n的值非常小,因为,在这个问题中增加一个元素就导致运行时间加倍。不幸的是,确实有许多问题 (如著名 的“巡回售货员问题”),到目前为止找到的算法都是指数的。如果我们真的遇到这种情况, 通常应该用寻找近似最佳结果的算法替代之。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/iluna/archive/2009/05/08/4159485.aspx
范文二:算法复杂度的计算
算法的复杂性是算法运行所需要的计算机资源的量,需要的时间资源的量称作时间复
杂性,需要的空间(即存储器)资源的量称作空间复杂性。这个量应该集中反映算法中所采
用的方法的效率,而从运行该算法的实际计算机中抽象出来。换句话说,这个量应该是只依
赖于算法要解的问题的规模、算法的输入和算法本身的函数。如果分别用N、I和A来表示
算法要解问题的规模、算法的输入和算法本身,用C表示算法的复杂性,那么应该有:
C =F(N,I,A)
其中F(N,I,A)是N,I,A的一个确定的三元函数。如果把时间复杂性和空间复杂性分开,并分
别用T和S来表示,那么应该有:
T =T(N,I,A) (2.1)
和 S =S(N,I,A) (2.2)
通常,我们让A隐含在复杂性函数名当中,因而将(2.1)和(2.2)分别简写为
T =T(N,I)
和 S =S(N,I)
由于时间复杂性和空间复杂性概念类同,计算方法相似,且空间复杂性分析相对地简
单些,所以下文将主要地讨论时间复杂性。
下面以T(N,I)为例,将复杂性函数具体化。
根据T(N,I)的概念,它应该是算法在一台抽象的计算机上运行所需的时间。设此抽象的
计算机所提供的元运算有k种,他们分别记为O,O,..,O;再设这些元运算每执行一次所12 k
需要的时间分别为t,t,..,t 。对于给定的算法A,设经过统计,用到元运算O的次数为e,12kiii=1,2,..,k ,很明显,对于每一个i,1<><=k,e是n和i的函数,即e=e(n,i)。那么有:>=k,e是n和i的函数,即e=e(n,i)。那么有:>
(2.3)
其中t,i=1,2,..,k,是与N,I无关的常数。 i
显然,我们不可能对规模N的每一种合法的输入I都去统计e(N,I),i=1,2,…,k。因此T(N,I)i
的表达式还得进一步简化,或者说,我们只能在规模为N的某些或某类有代表性的合法输
入中统计相应的e, i=1,2,…,k,评价时间复杂性。 i
下面只考虑三种情况的复杂性,即最坏情况、最好情况和平均情况下的时间复杂性,
并分别记为T(N )、T(N)和T(N )。在数学上有: maxminavg
(2.4)
(2.5)
(2.6)
* *其中,D是规模为N的合法输入的集合;I是D中一个使T(N,I)达到T(N)的合法输入,NNmax
是D中一个使T(N,)到T(N)的合法输入;而P(I)是在算法的应用中出现输入I 的概Nmin
率。
以上三种情况下的时间复杂性各从某一个角度来反映算法的效率,各有各的用处,也
各有各的局限性。但实践表明可操作性最好的且最有实际价值的是最坏情况下的时间复杂
性。下面我们将把对时间复杂性分析的主要兴趣放在这种情形上。
一般来说,最好情况和最坏情况的时间复杂性是很难计量的,原因是对于问题的任意
确定的规模N达到了T(N)的合法输入难以确定,而规模N的每一个输入的概率也难以预max
测或确定。我们有时也按平均情况计量时间复杂性,但那时在对P(I)做了一些人为的假设(比如等概率)之后才进行的。所做的假设是否符合实际总是缺乏根据。因此,在最好情况和平
均情况下的时间复杂性分析还仅仅是停留在理论上。
现在以上一章提到的问题1的算法Search为例来说明如何利用(2.4)-(2.6)对它的T、maxT和T进行计量。这里问题的规模以m计算,算法重用到的元运算有赋值、测试和加minavg
法等三种,它们每执行一次所需的时间常数分别为a,t,和s 。对于这个例子,如假设c在A中,那么容易直接看出最坏情况的输入出现在c=A[m]的情形,这时:
T(m)=a+2mt+(m-1)s+(m-1)a+t+a=(m+1)a+(2m+1)t+(m-1)s (2.7) max
而最好情况的输入出现在c=A[1]的情形。这时:
(2.8)
至于T(m),如前所述,必须对D上的概率分布做出假设才能计量。为简单起见,avgm
我们做最简单的假设:D上的概率分布是均等的,即P(A[i]=c)=1/m 。若记T=T(m,I),其mii
中I表示A[i]=c的合法输入,那么: i
(2.9) 而根据与(2.7)类似的推导,有:
代入(2.9) ,则:
这里碰巧有:
T(m)=(T(m)+T(m))/2 avgmaxmin
但必须指出,上式并不具有一般性。
类似地,对于算法B_Search照样可以按(2.4)-(2.6)计算相应的T(m)、T(m)和maxmin
T(m)。不过,我们这里只计算T(m) 。为了与Search比较,仍假设c在A中,即最avg max
坏情况的输入仍出现在c=A[m]时。这时,while循环的循环体恰好被执行了logm +1 即k+1 次。因为第一次执行时数据的规模为m,第二次执行时规模为m/2等等,最后一次执行时规模为1。另外,与Search少有不同的是这里除了用到赋值、测试和加法三种原运算外,
还用到减法和除法两种元运算。补记后两种元运算每执行一次所需时间为b和d ,则可以推演出:
(2.10) 比较(2.7)和(2.10) ,我们看到m充分大时,在最坏情况下B_Search的时间复杂性远小于Search的时间复杂性。
范文三:如何计算时间复杂度
如何计算计计计计度
求解算法的计计计计度的具步计是, 体
? 出算法中的基本计句~找
算法中计行次最多的那计句就是基本计句~通常是最计循计的循计。数条内体
? 计算基本计句的计行次的量计~数数
只需计算基本计句计行次的量计~计就意味着只要保计基本计句计行次的函数数数
数确即数中的最高次计正可~可以忽略所有低次计和最高次计的系。计计能计计化算法分析~且使注意力集中在最重要的一点上,增计率。并
? 用大Ο计表示算法的计计性能。号
基本计句计行次的量计放入大将数数Ο计中。号
如果算法中包含嵌套的循计~计基本计句通常是最计的循计~如果算法中包内体
含列的循计~计列循计的计计计计度相加。例如,并将并
for (i=1; i<=n;>=n;>
x++;
for (i=1; i<=n;>=n;>
for (j=1; j<=n;>=n;>
x++;
第一个for循计的计计计计度计Ο(n)~第二个for循计的计计计计度计Ο(n2)~计整算个法的计计计计度计Ο(n+n2)=Ο(n2)。
常计的算法计计计计度由小到大依次计,
Ο(1),Ο(log2n),Ο(n),Ο(nlog2n),Ο(n2),Ο(n3),…,Ο(2n),
Ο(n!)
Ο(1)表示基本计句的计行次是一常~一般计~只要算法中不存在循计计句数个数来~
其计计计计度就是Ο(1)。Ο(log2n)、Ο(n)、Ο(nlog2n)、Ο(n2)和Ο(n3)计多计称式计计~而Ο(2n)和Ο(n!)计指 计计。计算机科家普遍计计前者是有效算法~把称数学
计计计计计称P计计计~而把后者计称NP计计。
计只能基本的计算计计计计度~具的行计硬件有计。体运会与
上面的计部分容是比计可的~理解的计候~可以看着下面的计部分容。内靠参内
在计算算法计计计计度计有以下计计的程序分析法计几个:
1.计于一些计计的计入计出计句或计计计句,近似计计需要O(1)计计2.计于计序计构,需要依次计行一系列计句所用的计计可采用大O下"求和法计"求和法计:是指若算法的2部分计计计计度分计计 个T1(n)=O(f(n))和 T2(n)=O(g(n)),计
T1(n)+T2(n)=O(max(f(n), g(n)))特计地,若T1(m)=O(f(m)), T2(n)=O(g(n)),计 T1(m)+T2(n)=O(f(m) + g(n))
3.计于计计计构,如if计句,的主要计计耗计是在计行它then字句或else字句所用的计计,需注意的是计计件也需要条O(1)计计
4.计于循计计构,循计计句的行计计主要计在多次迭代中计行循计以及计计循计件的计计运体体条
耗计,一般可用大O下"乘法法计"
乘法法计: 是指若算法的2部分计计计计度分计计 个T1(n)=O(f(n))和 T2(n)=O(g(n)),
计 T1*T2=O(f(n)*g(n))
5.计于计计的算法,可以分成容易算的部分将它几个估,然后利用求和法计和乘法法计
技计整算法的计计计计度个
另外计有以下2算法计个运:
(1) 若g(n)=O(f(n)),计O(f(n))+ O(g(n))= O(f(n))(2) O(Cf(n)) = O(f(n)),其中C是一正常个数
可以用以上法计计下面程序段计行计计分析
?for (i=0; i
? for (j=0; j
{
? c[i][j] = 0;
? for (k=0; k
? c[i][j]= c[i][j]+ a[i][k]* b[k][j];/ * T5(n) = O(1) */}
第?????是循计嵌套条与T1(n)*T2(n)* (T3(n)+ T4(n)* T5(n))= O(n*n*n)计整算法的计计计计度即个
O(1)<><>
范文四:时间复杂度的计算
时间复杂度计算
首一个算法中的语句执行次数称为语句频度或时间频度,记为T(n)。n 称为问题的规模,当n 不断变化时,时间频度T(n)也会不断变化。但是有时候,我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。
一般情况下,算法中基本操作重复执行的次数,是问题规模 n 的某个函数,用T(n)表示。若有某个辅助函数f(n),使得当n 趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度。
时间频度不相同时,渐进时间复杂度O(f(n)) 有可能相同,如
T(n)=n^2+3n+4与T(n)=4n^2+2n+1它们的频度不同,但时间复杂度相同,都为O(n^2)。
?现在我们根据一些书本上和网络上对时间复杂度概念的描述进行一下总结: T(n),语句频度,时间频度,亦称为时间复杂度。
O(f(n)),渐进时间复杂度。
前者T(n)是某个算法的时间耗费,它是该算法所求解 问题规模 n的函数,而后者O(f(n))是指当问题规模趋向无穷大时,该算法时间复杂度的数量级。当我们评价一个算法的时间性能时,主要标准就是算法的渐近时间复杂度O(f(n)),因此,在算法分析时,往往对两者不予区分,经常是将渐近时间复杂度
T(n)=O(f(n))简称为时间复杂度,其中的f(n)一般是算法中频度最大的语句频度。
注意:算法中语句的频度不仅与问题规模有关,还与输入实例中各元素的取值相关。但是我们总是考虑在最坏的情况下的时间复杂度。以保证算法的运行时间不会比它更长。常见的时间复杂度,按数量级递增排列依次为:常数阶O(1)、对数阶O(log2n)、线性阶O(n)、线性对数阶O(nlog2n)、平方阶O(n^2)、立方阶O(n^3)、k 次方阶O(n^k)、指数阶O(2^n)。
1. 大O 表示法
定义
设一个程序的时间复杂度用一个函数 T(n) 来表示,对于一个查找算法,如下:
int seqsearch( int a[], const int n, const int x)
{
int i = 0;
for (; a[i] != x && i < n="" ;="" i++="">
if ( i == n) return -1;
else return i;
}
这个程序是将输入的数值顺序地与数组中地元素逐个比较,找出与之相等地元素。
在第一个元素就找到需要比较一次,在第二个元素找到需要比较2次,…… ,在第n 个元素找到需要比较n 次。对于有n 个元素的数组,如果每个元素被找到的概率相等,那么查找成功的平均比较次数为:
f(n) = 1/n (n + (n-1) + (n-2) + ... + 1) = (n+1)/2 = O(n)
这就是传说中的大O 函数的原始定义。
这里我们复习一下渐近时间复杂度的表示法T(n)=O(f(n)),这里的"O" 是数学符号,它的严格定义是 "若T(n)和f(n)是定义在正整数集合上的两个函数,则T(n)=O(f(n))表示存在正常数C 和n0 , 使得当n ≥n0时都满足0≤T(n)≤C*f(n)。" (即书本中的定义)。通俗一点就是这两个函数当整型自变量n 趋向于无穷大时,两者的比值是一个不等于0的常数。
对于对数级,我们用大O 记法记为O(log2N)就可以了。
规则
1) 加法规则
T(n,m) = T1(n) + T2(n) = O ( max (f(n), g(m) )
2) 乘法规则
T(n,m) = T1(n) * T2(m) = O (f(n) * g(m))
3) 一个特例
在大O 表示法里面有一个特例,如果T1(n) = O?, c是一个与n 无关的任意常数,T2(n) = O ( f(n) ) 则有
T(n) = T1(n) * T2(n) = O ( c*f(n) ) = O( f(n) ).
也就是说,在大O 表示法中,任何非0正常数都属于同一数量级,记为O(1)。
4) 一个经验规则
有如下复杂度关系
c < log2n="">< n="">< n="" *="" log2n="">< n^2="">< n^3="">< 2^n="">< 3^n=""><>
其中c 是一个常量,如果一个算法的复杂度为c 、 log2N 、n 、 n*log2N , 那么这个算法时间效率比较高 ,如果是 2^n , 3^n ,n!, 那么稍微大一些的n 就会令这个算法不能动了,居于中间的几个则差强人意.
1)基本知识点:没有循环的一段程序的复杂度是常数,一层循环的复杂度是O(n),两层循环的复杂度是O(n^2)? (我用^2表示平方,同理 ^3表示立方);
1、设三个函数f,g,h 分别为 f(n)=100n^3+n^2+1000 , g(n)=25n^3+5000n^2 , h(n)=n^1.5+5000nlgn
请判断下列关系是否成立:
(1) f(n)=O(g(n))
(2) g(n)=O(f(n))
(3) h(n)=O(n^1.5)
(4) h(n)=O(nlgn)
这里我们复习一下渐近时间复杂度的表示法T(n)=O(f(n)),这里的"O" 是数学符号,它的严格定义是" 若T(n)和f(n)是定义在正整数集合上的两个函数,则T(n)=O(f(n))表示存在正的常数C 和n0 ,使得当n≥n0时都满足
0≤T(n)≤C?f(n)。" 用容易理解的话说就是这两个函数当整型自变量n 趋向于无穷大时,两者的比值是一个不等于0的常数。这么一来,就好计算了吧。
◆ (1)成立。题中由于两个函数的最高次项都是n^3,因此当n→∞时,两个函数的比值是一个常数,所以这个关系式是成立的。
◆ (2)成立。与上同理。
◆ (3)成立。与上同理。
◆ (4)不成立。由于当n→∞时n^1.5比nlgn 递增的快,所以h(n)与nlgn 的比值不是常数,故不成立。
2、设n 为正整数,利用大"O" 记号,将下列程序段的执行时间表示为n 的函数。
(1) i=1; k=0
while(i<>
{ k=k+10*i;i++;
}
解答:T(n)=n-1, T(n)=O(n), 这个函数是按线性阶递增的。
(2) x=n; // n>1
while (x>=(y+1)*(y+1))
y++;
解答:T(n)=n1的平方根 ,T(n)=O(n1的平方根) ,最坏的情况是y=0,那么循环的次数是n1的平方根次,这是一个按平方根阶递增的函数。
(3) x=91; y=100;
while(y>0)
if(x>100)
{x=x-10;y--;}
else x++;
解答: T(n)=O(1),这个程序看起来有点吓人,总共循环运行了1000次,但是我们看到n 没有? 没。这段程序的运行是和n 无关的,就算它再循环一万年,我们也不管他,只是一个常数阶的函数。
同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适算法和改进算法。一个算法的评价主要从时间复杂度和空间复杂度来考虑。
1、时间复杂度
(1)时间频度
一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。
(2)时间复杂度
在刚才提到的时间频度中,n 称为问题的规模,当n 不断变化时,时间频度T(n)也会不断变化。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。
一般情况下,算法中基本操作重复执行的次数是问题规模n 的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n 趋近于无穷大时,T (n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
在各种不同算法中,若算法中语句执行次数为一个常数,则时间复杂度为O(1),
另外,在时间频度不相同时,时间复杂度有可能相同,如T(n)=n^2+3n+4与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n^2)。
按数量级递增排列,常见的时间复杂度有:
常数阶O(1),对数阶O(log2n),线性阶O(n),
线性对数阶O(nlog2n),平方阶O(n^2),立方阶O(n^3),...,
k 次方阶O(n^k),指数阶O(2^n)。随着问题规模n 的不断增大,上述时间复杂度不断增大,算法的执行效率越低。
2、空间复杂度
与时间复杂度类似,空间复杂度是指算法在计算机内执行时所需存储空间的度量。记作:
S(n)=O(f(n))
我们一般所讨论的是除正常占用内存开销外的辅助存储单元规模。讨论方法与时间复杂度类似,不再赘述。
(3)渐进时间复杂度评价算法时间性能
主要用算法时间复杂度的数量级(即算法的渐近时间复杂度) 评价一个算法的时间性能。
【例3.7】有两个算法A1和A2求解同一问题,时间复杂度分别是
T1(n)=100n^2,T2(n)=5n^3。
(1)当输入量n T2(n),后者花费的时间较少。
(2)随着问题规模n 的增大,两个算法的时间开销之比5n^3/100n^2=n/20亦随着增大。即当问题规模较大时,算法A1比算法A2要有效地多。
它们的渐近时间复杂度O(n^2)和O(n^3)从宏观上评价了这两个算法在时间方面的质量。在算法分析时,往往对算法的时间复杂度和渐近时间复杂度不予区分,而经常是将渐近时间复杂度T(n)=O(f(n))简称为时间复杂度,其中的f(n)一般是算法中频度最大的语句频度。
例1:
i=1; k=0
while(i<>
{ k=k+10*i;i++;
}
解答:T(n)=n-1, T(n)=O(n), 这个函数是按线性阶递增的。
例2:
a=0;
b=1; ①
for (i=1;i<=n;i++)>=n;i++)>
{
s=a+b; ③
b=a; ④
a=s; ⑤
}
解: 语句1的频度:2,
语句2的频度: n,
语句3的频度: n-1,
语句4的频度:n-1,
语句5的频度:n-1, T(n)=2+n+3(n-1)=4n-1=O(n).
O(n^2)
例1: 交换i 和j 的内容
sum=0; (一次)
for(i=1;i<=n;i++) (n="" 次="">=n;i++)>
for(j=1;j<=n;j++) (n^2次="">=n;j++)>
sum++; (n^2次 ) (此语句是算法中频度最大的,可
直接算出f(n)=n^2,得时间复杂度T(n)=O(n^2))
解:T(n)=2n^2+n+1 =O(n^2)
例2:
for (i=1;i<>
{
y=y+1; ①
for (j=0;j<>
x++; ②
}
解: 语句1的频度是n-1
语句2的频度是(n-1)*(2n+1)=2n^2-n-1
f(n)=2n^2-n-1+(n-1)=2n^2-2
该程序的时间复杂度T(n)=O(n^2).
O(n^3)
例1:
for(i=0;i<>
{
for(j=0;j<>
{
for(k=0;k<>
x=x+2; (此语句为频度最大的语句,可算出f(n)=n^3,写出时间复杂度T(n)=O(n^3))
}
}
解:当i=m, j=k的时候, 内层循环的次数为k 当i=m时, j 可以取
0,1,...,m-1 , 所以这里最内循环共进行了0+1+...+m-1=(m-1)m/2次所以,i 从0取到n, 则循环共进行了:
0+(1-1)*1/2+...+(n-1)n/2=n(n+1)(n-1)/6所以时间复杂度为O(n^3).
O(log2n )
(此为例外情况,难以算出T(n),但可以利用技巧直接算出O(f(n))。) 例1:
i=1; ①
while (i<>
i=i*2; ②
解: 语句1的频度是1,
设语句2的频度是f(n), 则:2^f(n)<><=log2n 取最大值f(n)="">=log2n>
T(n)=O(log2n )
平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,算法的期望运行时间。
常见的时间复杂度按数量级递增排列依次为:常数0(1)、对数阶0(log2n)、线形阶0(n)、线形对数阶0(nlog2n)、平方阶0(n^2)立方阶、0(n^3)、…、k 次方阶0(n^k)、指数阶0(2^n)。显然,时间复杂度为指数阶0(2^n)的算法效率极低,当n 值稍大时就无法应用。
类似于时间复杂度的讨论,一个算法的空间复杂度(Space
Complexity)S(n)定义为该算法所耗费的存储空间,它也是问题规模n 的函数。渐近空间复杂度也常常简称为空间复杂度。算法的时间复杂度和空间复杂度合称为算法的复杂度。
范文五:计算复杂度研究现状
计算复杂性理论研究现状
摘 要
根据对多项式时间复杂性的存在算法,得出计算复杂性理论把问题按其复杂性分为三大类:存在多项式时间复杂性的问题;肯定不存在多项式时间算法的问题,即具有指数时间复杂性问题;未找到多项式算法,不证明不存在多项式算法。计算复杂性理论是计算机科学理论的一个重要组成部分,当代几乎所有重要的科学问题都与计算复杂性有关,如人工智能问题,认识极限问题等,这些问题都是当代科学前沿的一些重要但未解决的问题。计算复杂性理论正在被人们进行深入的研究,研究的焦点一般集中于NP=? P和设法解NPC问题上,随着计算复杂性理论研究的不断深入,计算机科学理论得到了飞速的发展。
关键词:多项式时间复杂性;NP类;NPC问题
1 图灵机(TM)
图灵机是一种重要的计算模型,是由英国数理逻辑学家A1M1Turing于1936年提出的。它的基本结构思想为1946年计算机的问世在理论上奠定了基础。图灵机不仅可以作为语言识别器,而且可以计算函数,其中,原始的是实现对整函数的计算。从读写带的条数来分,图灵机有一条带的图灵机和多条带的图灵机;从动作函数来分,图灵机有确定的图灵机和不确定的图灵机,不确定的图灵机同确定的图灵机的区别在于它的动作函数D是一个多值映射
从理论上说,有理数可以表示成自然数序偶,实数可以表示成自然数序列(其近似值为有限序列),而非数值信息通常可用自然数编码来处理。因此,图灵机可计算函
数包含了迄今为止所有的可计算函数。
图灵机是一种实际可计算的理想机,故图灵机的可计算问题是计算机中可计算性的理论基础,可计算理论早已发展成为一门独立的学科。
2 可计算函数
首先给出完全递归函数的定义如下。
定义211 若存在图灵机TM实现函数f的计算功能,而且对于任意一组输入(i1, i2,+, in),TM都能停机,则称函数f为一个完全递归函数。
定义212 一个函数f是可计算函数,当且仅当f是一个完全递归函数。对于可计算函数,可以设计算法进入计算,而且对于每一个输入,算法都能终止,并且输出计算结果。
3 计算复杂性
计算复杂性是计算机科学理论的一个重要组成部分,计算复杂性包括时间复杂性和空间复杂性。研究问题的计算复杂性是为了找出解决该问题而其复杂性又达到最低(阶)的算法,特别是使时间复杂性达到最低(阶)的算法。
定义311 对于一个问题Q,称其时间复杂性为T(n)(其空间复杂性为S(n)),若存在一个计算问题Q的图灵机,它以T(n)为时间界(以S(n)为空间界)。
时间复杂性一般分为多项式时间复杂性和指数时间复杂性两种,多项式时间复杂性是指可用多项式来对问题的计算时间界定,而指数时间复杂性是指可用指数来对问题的计算时间界定,常见的6种多项式计算时间函数及它们之间的关系是 O(1)
而常见的三种指数计算时间函数和它们之间的关系是
O(2n)
具有多项式时间复杂性的问题是可解的,但是具有指数时间复杂性的问题在实践中并不一定是可解的,这是因为求解该问题的算法可能需要极长的机器运行时间和极大的存储空间,使得在现有的计算机上根本就是无法实现,例如,货郎担问题(traveling salesperson problem,TSP)中,当问题规模(访问城市个数)为n,那么TSP共进行的比较操作次数
n(n-1)!/2-1,当访问的城市数为10个,计算机的运行速度为1Mflops(每秒一百万次浮点运算),则所需机器时间为0.118 s;而当访问城市为20个时,所需机器时间长达1929年,显然这个时间是无法容忍的,这类问题只能用近似方法或启发式方法求解。如果能将具有指数时间复杂性的问题转化为具有多项式时间复杂性,那就取得了一个可喜的成就。
4 P类和NP类
一个问题是否存在多项式时间复杂性的求解算法,是人们关心的问题之一,如果一个问题存在多项式时间复杂性的求解算法(即其计算时间(步数)可表示为输入量的多项式函数),那么这个问题就可以借助计算机来实现求解。反之,如果算法所需要的时间(步数)是输入量的指数函数,如T(n)=2n,那么当n很大时(如n\64),T(n)就是一个很大的数量,用计算机是无法在有效的时间内实现求解的。
定义411 用确定的图灵机(DTM)在多项式时间界内可求解的问题称为P类问题;用不确定的图灵机(NTM)在多项式时间界内可求解的问题称为NP类问题。
由于DTM是NTM的一种特殊情形,因此显然有PANP,但问题是是否有NP=P?
问题NP=? P的重要性是明显的,有许多问题(至少几百个),如等划分问题,布尔表达式的可满足性问题等,现已给出了多项式时间的NTM求解方法,但未给出多项式时间的DTM求解方法,如果NP=P,那么上述问题就都可以找出多项式时间的计算机算法。 NP=? P是当今计算机科学中有代表性的难题之一。至今未能证明NPXP,也求能证
明NP=P。美国克雷斯研究所悬赏100万美元对7个问题征解, NP=? P的问题列在7个问题之首。在20~21世纪之交,中国科协组织200位科学家写了一本书名为521世纪的100个科学难题6的书,NP=? P问题也列在其中。
5 NP-完全问题
NP-完全问题是计算复杂性理论中最重要的一部分,这方面的研究结果对于计算机算法研究和运筹学研究等方面的工作都是十分有用的。首先给出NP困难问题的定义 如下。
定义511 设一个问题Q1满足条件:PQINP都有Q
WQ1,则称Q1为一个NP困难问题。NP困难问题是求解/难度0(时间复杂性)不小于任意
NP类问题的一类问题。若Q1可以有多项式的时间界的求解算法,则任意一个NP问题都可以有多项式时间界的求解算法。
定义512 若问题Q1INP且PQINP都有QWQ1,则称Q1为一个NP完全(NPC)问题,记为Q1INPC。NP完全问题的意义在于:如果Q1INPC,则由于Q1INP,若Q1IP,就可以肯定所有的NP类问题都有多项式的确定算法。也就是说, NPC问题是NP类问题中最难的问
题。下列定理说明了NPC问题的意义。
定理511 设Q1INPC,那么NP=P当且仅当Q1IP。
定理511表明,如果能找到一个NPC问题Q1,对Q1找出了多项式算法,那么所有的NP类问题都存在多项式算法,即有NP=P。这样就把NP=P?的问题转化为对某一个(任意一个)NPC问题找出多项式算法的问题。
当然定理511还有另一层意思:只要证明其中某一个(任意一个)NPC问题不存在多项式算法,那么所有的NPC问题都不存在多项式算法,从而证明了NPXP。可见,对某
一个NPC问题给出多项式算法,或者证明某一个NPC问题不存在多项式算法成为回答NP=? P的关键问题。
从定义511和定义512看出,NPC问题是NP类问题中的NP困难问题,或者说是NP类问题中/最难0的一个问题子类,由于P类问题也是NP类的一个子类(这是相对不那么困难的一个子类)。如果能够找到NPC和P的一个交点(即找到一个问题Q1IPC且Q1IP),那么就会推出NPC=P=NP。为了寻找NPC和P的交点,人们首先着眼于寻找NPC的元素。1971年Cook找出了第1个NPC问题,从而证明了NPC问题是确实存在的,这被认为是一个划时代的结果。他证明了布尔表达式的可满足性问题是一个NPC问题,这就是著名的Cook定理。
定理512 (Cook定理)布尔表达式的可满足性问题是一个NPC问题。
在Cook定理之后,有人通过把布尔表达式的可满足性问题多项式归纳为命题演算舍取范围的可满足性问题,证明了命题演算舍取范围的可满足性问题也是一个NPC问题。现在已经找出的NPC问题已有300多个。
这样,如果某一个NPC问题确实存在于P类中,那么P类和NP类重合,即有NP=P。这一命题的巨大的意义在于现已证明像装箱、路径、调度等许多组合问题以及其他科学领域中的一大批问题都是NP完全的。NPC问题是NP类中最难的问题,如果对于NPC问题中任意一个问题存在有多项式时间算法,则整个NP类问题都存在多项式时间算法,从而也就证明了NP=P的命题。然而,这个命题至今没有得到证明。因此,计算科学家们大都认为NP完全问题不存
在有效的多项式算法,即有NPXP。于是,事实上就形成了所谓的NP=? P的问题。 NP=? P问题的研究受到科学家们的高度重视,并且逐渐形成了三个主要的学派.
(1)传统概念学派。传统概念学派坚持以图灵机、图灵可计算等传统概念来研究NP=? P问题,他们是这一问题研究的主流。这一学派提出了一些新方法、新思想,比如:关于布尔线路下界、多项式时间分层、多项式归纳、交互式证明系统、one-way函数和程序复杂性等研究,这些成果有力地加深了对NP=? P的研究。
(2)人工智能学派。因为大多数组合问题的算法都是NP完成的,在现实机器的存储资源和机器运行时间条件下,很难得到或根本得不到最优解。而在许多实际的应用问题中,令人满意解并非一定是最优解。所以,放弃寻求最优解,而去研究启发式搜索算法以及相应的概率分析。这种方法是以牺牲完全性换取高效率和满意解,它在人工智能的应用中取得了很好的效果。
(3)变革学派。随着人工智能和认知科学的不断深人发展,NP=? P问题又长期未能得到满意的解决,因此应突破传统的图灵计算等概念,探讨新的研究方法成为变革学派的主张。例如Clark提出不能把计算纳结为符号变换,应该研究形式符号系统和连续信号处理系统之间的关系,也有人认为人脑是一个开放式系统,计算机也应该是开放的,应该用开放的模型去计算。
6 结 论
(1)如果对某个NPC问题设计出确定算法,那么就证明了NP=P,即全部NP问题都是多项式可解的。看来做到这一点的可能性不大,过去许多算法工作者企图解决这个问题,都未取得成功。
(2)如果证明了某个NPC问题肯定不存在确定的多项式算法,那么所有的NPC问题也不存在确定的多项式算法。亦即说明了NPC问题是真正困难的问题。
(3)通过多项式归纳等手段继续发掘出一些NPC问题,扩大NPC问题的范围。 问题NP=? P是计算科学中引人瞩目的大课题, NPC问题的提出和研究就是为了最终解决这个问题,然而NPC问题的提出和所取得的成果虽然使NP=? P的问题向前迈出了一大步,然而最终的一步(也是最关键的一步)却历经30多年都未完成:即没有对其中某个NPC问题给出多项式算法,也没有证明某个NPC问题不存在多项式算法。NP完全问题是近20年来算法研究中最重要的理论发展,这方面的研究结果对于计算机算法研究和运筹学研究等方面的工作都是十分有用的。最近, Spielman和Teng提出了平滑复杂性概念及复杂性平滑分析方法,在理论计算机科学界引起了极大的关注,可以相信,随着计算复杂性的研究的不断深入,会促进计算机科学与理论
的飞速发展。
参考文献:
[1] 陈志平,徐宗本1计算机数学)))计算复杂性理论与NPC、NP难问题的求解[M]1北京:科学出版社, 20031
[2] 堵丁柱,葛可一,王洁1计算复杂性导论[J]1高等教育出版社, 20021