算法的复杂度

算法的复杂度

算法效率的度量是通过时间复杂度和空间复杂度来描述的。

一.时间复杂度

—个语句的频度是指该语句在算法中被重复执行的次数。算法中所有语句的频度之和记作T(n),它是该算法问题规模n的函数,时间复杂度主要分析T(n)的数量级。算法中的基本运算(最深层循环内的语句)的频度与T(n)同数量级,所以通常采用算法中基本运算的频度制来分析算法的时间复杂度。因此,算法的时间复杂度也记为:

T(n)=O(f(n))

上式中“O”的含义是T(n)的数量级,其严格的数学定义是:若T(n)和f(n)是定义在正整数集合上的两个函数,则存在正常数C和no,使得当n>=no时,都满足0<=T(n)<=C*F(n)。 算法的时间复杂度不仅依赖于问题的规模n,也取决于待输入数据的性质(如输入数据元素的初始状态)。

(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)) 为算法的渐进时间复杂度,简称时间复杂度。
     时间频度不同,但时间复杂度可能相同。如:T(n)=n2+3n+4与T(n)=4n2+2n+1它们的频度不同,但时间复杂度相同,都为O(n2)。
    按数量级递增排列,常见的时间复杂度有:常数阶O(1),对数阶O(log2n),线性阶O(n), 线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),..., k次方阶O(nk),指数阶O(2n)。随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。

(3)最坏时间复杂度、平均时间复杂度和最好时间复杂度

最坏时间复杂度是指在最坏情况下,算法的时间复杂度。
平均时间复杂度是指所有可能输入实例在等概率出现的情况下,算法的期望运行时间。
最好时间复杂度是指在最好情况下,算法的时间复杂度。

最坏情况下的时间复杂度称最坏时间复杂度。一般不特别说明,讨论的时间复杂度均是最坏情况下的时间复杂度。 这样做的原因是:最坏情况下的时间复杂度是算法在任何输入实例上运行时间的上界,这就保证了算法的运行时间不会比任何更长。
     在最坏情况下的时间复杂度为T(n)=0(n),它表示对于任何输入实例,该算法的运行时间不可能大于0(n)。 平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,算法的期望运行时间。
    指数阶0(2n),显然,时间复杂度为指数阶0(2n)的算法效率极低,当n值稍大时就无法应用。

(4)时间复杂性两条规则

a)加法规则
T(n)=T1(n)+T2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n)))
b)乘法规则
T(n)=T1(n)xT2(n)=O(f(n))*O(g(n))=O(f(n)*g(n))

常见的渐近时间复杂度有:

(5)求时间复杂度
【1】如果算法的执行时间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。

x=91; y=100;
while(y>0) if(x>100) {x=x-10;y--;} else x++;

解答: T(n)=O(1),
这个程序看起来有点吓人,总共循环运行了1000次,但是这段程序的运行是和n无关的,只是一个常数阶的函数。

【2】当有若干个循环语句时,算法的时间复杂度是由嵌套层数最多的循环语句中最内层语句的频度f(n)决定的。

A

x=2;
while(x<n/2)
   x=2*x;

在程序中,执行频率最高的语句为“x=2*x”。设该语句共执行了t次,设2t+1=n/2,故 t=log2(n/2>-1 = log2n-2,得 T(n)=0(log2n)。

B

int m=0,i,j;
for (i=1;i<=n;i++)
   for (j=1;j<=2*i;j++)
       m++;

m++语句的执行次数为

【3】算法的时间复杂度不仅仅依赖于问题的规模,还与输入实例的初始状态有关。
在数值A[0..n-1]中查找给定值K的算法大致如下:

i=n-1;
while(i>=0&&(A[i]!=k))
      i--;
return i;

此算法中的语句(3)的频度不仅与问题规模n有关,还与输入实例中A的各元素取值及K的取值有关: ①若A中没有与K相等的元素,则语句(3)的频度f(n)=n; ②若A的最后一个元素等于K,则语句(3)的频度f(n)是常数0。

(6)时间复杂度评价性能
有两个算法A1和A2求解同一问题,时间复杂度分别是T1(n)=100n2,T2(n)=5n3。(1)当输入量n<20时,有T1(n)>T2(n),后者花费的时间较少。(2)随着问题规模n的增大,两个算法的时间开销之比5n3/100n2=n/20亦随着增大。即当问题规模较大时,算法A1比算法A2要有效地多。它们的渐近时间复杂度O(n2)和O(n3)从宏观上评价了这两个算法在时间方面的质量。在算法分析时,往往对算法的时间复杂度和渐近时间复杂度不予区分,而经常是将渐近时间复杂度T(n)=O(f(n))简称为时间复杂度,其中的f(n)一般是算法中频度最大的语句频度。

二.空间复杂度

一个程序的空间复杂度是指运行完一个程序所需内存的大小。利用程序的空间复杂度,可以对程序的运行所需要的内存多少有个预先估计。一个程序执行时除了需要存储空间和存储本身所使用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为现实计算所需信息的辅助空间。程序执行时所需存储空间包括以下两部分。  
(1)固定部分。这部分空间的大小与输入/输出的数据的个数多少、数值无关。主要包括指令空间(即代码空间)、数据空间(常量、简单变量)等所占的空间。这部分属于静态空间。
(2)可变空间,这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。这部分的空间大小与算法有关。
一个算法所需的存储空间用f(n)表示。S(n)=O(f(n))  其中n为问题的规模,S(n)表示空间复杂度。

算法原地工作是指算法所需辅助空间是常量,即O(1)。

以交换排序为例:

冒泡排序:仅适用了常数个辅助单元(用于相邻数据的交换),因而空间复杂度为O(1)。

快速排序:由于快排是递归的,需要借助于一个递归工作栈来保存每一层递归调用的必要信息,其容量与递归调用的最大深度一致。最坏情况下:O(n),平均情况下O(log2n)。

-------------------------------------------------------------------------------------------------------------------------------------

时间: 2024-10-12 13:56:23

算法的复杂度的相关文章

算法的时间复杂度和空间复杂度合称为算法的复杂度

算法的时间复杂度和空间复杂度合称为算法的复杂度. 1.时间复杂度 (1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道.但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了.并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多.一个算法中的语句执行次数称为语句频度或时间频度.记为T(n). (2)时间复杂度 在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时

【转】算法的复杂度

算法的时间复杂度和空间复杂度合称为算法的复杂度. 1.时间复杂度 (1)时间频度 一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道.但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了.并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多.一个算法中的语句执行次数称为语句频度或时间频度.记为T(n). (2)时间复杂度 在刚才提到的时间频度中,n称为问题的规模,当n不断变化时,时

比较排序算法及复杂度分析

比较排序算法分类 比较排序(Comparison Sort)通过对数组中的元素进行比较来实现排序. 比较排序算法(Comparison Sorts) Category Name Best Average Worst Memory Stability  插入排序  (Insertion Sorts) 插入排序 (Insertion Sort) n n2 n2 1 Stable 希尔排序 (Shell Sort) n n log2 n n log2 n 1 Not Stable  交换排序 (Exc

python学习笔记-Day027 - 算法的复杂度

算法是处理问题的步骤(就像错菜的菜谱) 算法的时间复杂度 和空间复杂度合成为算法的复杂度 时间复杂度 首先 提到一个 时间频度 T(n),一个算法中语句的执行次数 称为时间频度 也叫 语句频度 . 一个算法执行所耗费的时间,理论上说是能算出来的,必须上级测试才可以得到,但是没必要对所有个的算法都上机测试,我们只要知道哪个算法耗费的时间多,哪个算法耗费的时间少就可以了.在一个算法中,算法花费的时间与算法中语句的执行次数成正比,哪个算法中语句的执行次数多,那么他耗费的时间就多. 在刚才提到 T(n)

计算机科学及编程导论(8)算法的复杂度

1.基于问题规模的复杂度计算方法 在考虑时间效率的时候,面临以下两个问题:输入规模以及步骤. 输入规模受很多因素影响:参数大小.参数类型(数组.元组的存取小绿是不同的),而且不同操作步骤(加减.判断)时间也不是相同的,为了方便计算,我们需要建立以下的假设: 假设从计算机取得任何变量的时间是相同的 假设基本操作时间恒定 接下来就可以考虑以下几种情况: 最好情况:何种输入会使得程序的运行时间最短? 最坏情况:何种输入会使得程序的运行时间最长? 平均情况 如果考虑平均情况的话,就要去设想问题输入规模的

几种简单的求素数算法的复杂度分析

素数的算法有很多种,现在主要讲两种算法及其改进版本的复杂度分析,解释性能提升的幅度.现以求100000内素数为例,两种算法分别是: 1.基础思路是去掉偶数,包括取模的范围,代码如下: print(2) for i in range(3,100000,2): for a in range(3,int(i*0.5)+1,2): if i%a == 0: break else: print(i,end = ' ')此两层循环的算法的复杂度为0.5n((n**0.5+1)/2) 2.应用一个素数定理:大

算法的复杂度分析

这个是每个学习算法都必须掌握的东西.不过感觉又不太好说的清楚. 大概扯一下.就是因为每个计算机的运行的速度都不一定相同.所以需要一个标准来判断一个程序跑的快慢. 比如一个简单的for循环.for(int i = 0; i < n; i++); 这个循环其实循环了n次.可能在不同的机器上跑的时间不同. 但是都一定会跑n次.所以用O(n)来表示这个循环的时间复杂度. 再举一个例子 for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++

各种排序算法的复杂度和稳定性

名称 数据对象 稳定性 时间复杂度 ?? 空间复杂度 描述 ?? ?? ?? 平均 最坏 ?? ?? 冒泡排序 数组 ?? (无序区,有序区).从无序区通过交换找出最大元素放到有序区前端. 选择排序 数组 ?? (有序区,无序区).在无序区里找一个最小的元素跟在有序区的后面.对数组:比较得多,换得少. ?? 链表 ?? ?? ?? ?? 插入排序 数组.链表 ?? (有序区,无序区).把无序区的第一个元素插入到有序区的合适的位置.对数组:比较得少,换得多. 堆排序 数组 ?? (最大堆,有序区)

算法的复杂度包括时间复杂度和空间复杂度分别如何计算?

一 .时间复杂度 一.概念 时间复杂度是总运算次数表达式中受n的变化影响最大的那一项(不含系数) 比如:一般总运算次数表达式类似于这样: a*2n+b*n3+c*n2+d*n*lg(n)+e*n+f a ! =0时,时间复杂度就是O(2n); a=0,b<>0 =>O(n3); a,b=0,c<>0 =>O(n2)依此类推 例子: (1) for(i=1;i<=n;i++) //循环了n*n次,当然是O(n2) for(j=1;j<=n;j++) s++;