一个算法的优劣往往通过算法复杂度来衡量,算法复杂度包括时间复杂度和空间复杂度。

时间复杂度是算法的所需要消耗的时间,时间越短,算法越好。可以对算法的代码进行估计,而得到算法的时间复杂度。

一般来说,算法代码简短精悍可以用来减少算法的时间复杂度!

空间复杂度指的是算法程序在执行时所需要的存储空间。空间复杂度可以分为以下两个方面!

1.程序的保存所需要的存储空间资源。即程序的大小;

2.程序在执行过程中所需要消耗的存储空间资源,如中间变量等;

一般来说,程序的大小越小,执行过程中消耗的资源越少,这个程序就越好!

下面为时间复杂度和空间复杂度的计算

时间复杂度是总运算次数表达式中受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++;
(2)   for(i=1;i<=n;i++)//循环了(n+n-1+n-2+...+1)≈(n2)/2,因为时间复杂度是不考虑系数的,所以也是O(n2)for(j=i;j<=n;j++)s++;
(3)   for(i=1;i<=n;i++)//循环了(1+2+3+...+n)≈(n^2)/2,当然也是O(n2)for(j=1;j<=i;j++)s++;
(4)   i=1;k=0;//循环了n-1≈n次,所以是O(n)while(i<=n-1){k+=10*i;
i++; }
(5) for(i=1;i<=n;i++)for(j=1;j<=i;j++)for(k=1;k<=j;k++)x=x+1;
//
循环了(1

2

+2

2

+3

2

+...+n

2

)=n(n+1)(2n+1)/6(这个公式要记住哦)≈(n

3

)/3,不考虑系数,自然是O(n

3

)
另外,在时间复杂度中,log

2

n与lg(n)(同lg

10

(n))是等价的,因为对数换底公式:
log

a

b=log

c

b/log

c

a
所以,log

2

n=log

2

10 * lg(n),忽略掉系数,二者当然是等价的
二、计算方法
1.一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。
一个算法中的语句执行次数称为语句频度或时间频度。记为T(n)。
2.一般情况下,算法的基本操作重复执行的次数是模块n的某一个函数f(n),因此,算法的时间复杂度记做:T(n)=O(f(n))。随着模块n的增大,算法执行的时间的增长率和f(n)的增长率成正比,所以f(n)越小,算法的时间复杂度越低,算法的效率越高。
在计算时间复杂度的时候,先找出算法的基本操作,然后根据相应的各语句确定它的执行次数,再找出T(n)的同数量级(它的同数量级有以下:1,Log

2

n ,n ,nLog

2

n ,n的平方,n的三次方,2的n次方,n!),找出后,f(n)=该数量级,若T(n)/f(n)求极限可得到一常数c,则时间复杂度T(n)=O(f(n))。
3.常见的时间复杂度
按数量级递增排列,常见的时间复杂度有:
常数阶O(1),  对数阶O(log

2

n),  线性阶O(n),  线性对数阶O(nlog

2

n),  平方阶O(n

2

), 立方阶O(n

3

),..., k次方阶O(n

k

), 指数阶O(2

n

) 。
其中,
1.O(n),O(n

2

), 立方阶O(n

3

),..., k次方阶O(n

k

) 为多项式阶时间复杂度,分别称为一阶时间复杂度,二阶时间复杂度。。。。
2.O(2

n

),指数阶时间复杂度,该种不实用
3.对数阶O(log

2

n),   线性对数阶O(nlog

2

n),除了常数阶以外,该种效率最高
例:算法:for(i=1;i<=n;++i){for(j=1;j<=n;++j){c[ i ][ j ]=0; //该步骤属于基本操作 执行次数:n

2

          for(k=1;k<=n;++k)c[ i ][ j ]+=a[ i ][ k ]*b[ k ][ j ]; //该步骤属于基本操作 执行次数:n

3

     }}则有 T(n)= n

2

+n

3

,根据上面括号里的同数量级,我们可以确定 n

3

为T(n)的同数量级则有f(n)= n

3

,然后根据T(n)/f(n)求极限可得到常数c则该算法的 时间复杂度:T(n)=O(n

3

)
四、定义:如果一个问题的规模是n,解这一问题的某一算法所需要的时间为T(n),它是n的某一函数 T(n)称为这一算法的“时间复杂性”。
当输入量n逐渐加大时,时间复杂性的极限情形称为算法的“渐近时间复杂性”。
我们常用大O表示法表示时间复杂性,注意它是某一个算法的时间复杂性。大O表示只是说有上界,由定义如果f(n)=O(n),那显然成立f(n)=O(n^2),它给你一个上界,但并不是上确界,但人们在表示的时候一般都习惯表示前者。
此外,一个问题本身也有它的复杂性,如果某个算法的复杂性到达了这个问题复杂性的下界,那就称这样的算法是最佳算法。
“大O记法”:在这种描述中使用的基本参数是 n,即问题实例的规模,把复杂性或运行时间表达为n的函数。这里的“O”表示量级 (order),比如说“二分检索是 O(logn)的”,也就是说它需要“通过logn量级的步骤去检索一个规模为n的数组”记法 O ( f(n) )表示当 n增大时,运行时间至多将以正比于 f(n)的速度增长。
这种渐进估计对算法的理论分析和大致比较是非常有价值的,但在实践中细节也可能造成差异。例如,一个低附加代价的O(n2)算法在n较小的情况下可能比一个高附加代价的 O(nlogn)算法运行得更快。当然,随着n足够大以后,具有较慢上升函数的算法必然工作得更快。
O(1)
Temp=i;i=j;j=temp;
以上三条单个语句的频度均为1,该程序段的执行时间是一个与问题规模n无关的常数。算法的时间复杂度为常数阶,记作T(n)=O(1)。如果算法的执行时间不随着问题规模n的增加而增长,即使算法中有上千条语句,其执行时间也不过是一个较大的常数。此类算法的时间复杂度是O(1)。
O(n

2

) 1) 交换i和j的内容      sum=0;                 (一次)      for(i=1;i<=n;i++)       (n次 )         for(j=1;j<=n;j++) (n

2

次 )          sum++;       (n^2次 ) 解:T(n)=2n^2+n+1 =O(n^2)
2)        for (i=1;i<n;i++)     {         y=y+1;         //频度是n-1        for (j=0;j<=(2*n);j++)                x++;       //频度是(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)    a=0;     b=1;                     //频度:2    for (i=1;i<=n;i++) //频度: n    {         s=a+b;    //频度: n-1        b=a;     //频度:n-1         a=s;     //频度:n-1     }                  T(n)=2+n+3(n-1)=4n-1=O(n). 

O(log

2

n )4)      i=1;       //频度是1     while (i<=n)        i=i*2; //频度是f(n),   则:2

f(n)

<=n;f(n)<=log

2

n               取最大值f(n)= log

2

n,           T(n)=O(log

2

n )
O(n

3

)
5)  for(i=0;i<n;i++)     {      for(j=0;j<i;j++)          {           for(k=0;k<j;k++)              x=x+2;          }     } 解:当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(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的值非常小,因为,在 这个问题中增加一个元素就导致运行时间加倍。不幸的是,确实有许多问题 (如著名的“巡回售货员问题” ),到目前为止找到的算法都是指数的。如果我们真的遇到这种情况,通常应该用寻找近似最佳结果的算法替代之。

二.空间复杂度

空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度。一个算法在计算机存储器上所占用的存储空间,包括程序代码所占用的空间,输入数据所占用的空间和辅助变量所占用的空间这三个方面。算法的输入输出数据所占用的存储空间是由要解决的问题决定的,是通过参数表由调用函数传递而来的,它不随本算法的不同而改变。存储算法本身所占用的存储空间与算法书写的长短成正比,要压缩这方面的存储空间,就必须编写出较短的算法。算法在运行过程中临时占用的存储空间随算法的不同而异,有的算法只需要占用少量的临时工作单元,而且不随问题规模的大小而改变,我们称这种算法是“就地"进行的,是节省存储的算法,如这些介绍过的几个算法都是如此;有的算法需要占用的临时工作单元数与解决问题的规模n有关,它随着n的增大而增大,当n较大时,将占用较多的存储单元,例如将在第九章介绍的快速排序和归并排序算法就属于这种情况。分析一个算法所占用的存储空间要从各方面综合考虑。如对于递归算法来说,一般都比较简短,算法本身所占用的存储空间较少,但运行时需要一个附加堆栈,从而占用较多的临时工作单元;若写成非递归算法,一般可能比较长,算法本身占用的存储空间较多,但运行时将可能需要较少的存储单元。一个算法的空间复杂度只考虑在运行过程中为局部变量分配的存储空间的大小,它包括为参数表中形参变量分配的存储空间和为在函数体中定义的局部变量分配的存储空间两个部分。若一个算法为递归算法,其空间复杂度为递归所使用的堆栈空间的大小,它等于一次调用所分配的临时存储空间的大小乘以被调用的次数(即为递归调用的次数加1,这个1表不开始进行的一次非递归调用)。算法的空间复杂度一般也以数量级的形式给出。如当一个算法的空间复杂度为一个常量,即不随被处理数据量n的大小而改变时,可表示为O(1);当一个算法的空间复杂度与以2为底的n的对数成正比时,可表示为0(log

2

n);当一个算法的空I司复杂度与n成线性比例关系时,可表示为0(n).若形参为数组,则只需要为它分配一个存储由实参传送来的一个地址指针的空间,即一个机器字长空间;若形参为引用方式,则也只需要为其分配存储一个地址的空间,用它来存储对应实参变量的地址,以便由系统自动引用实参变量。对于一个算法,其时间复杂度和空间复杂度往往是相互影响的。当追求一个较好的时间复杂度时,可能会使空间复杂度的性能变差,即可能导致占用较多的存储空间;反之,当=i自求一个较好的空间复杂度时,可能会使时间复杂度的性能变差,即可能导致占用较长的运行时间。另外,算法的所有性能之间都存在着或多或少的相互影响。因此,当设计一个算法(特别是大型算法)时,要综合考虑算法的各项性能,算法的使用频率,算法处理的数据量的大小,算法描述语言的特性,算法运行的机器系统环境等各方面因素,才能够设计出比较好的算法。空间复杂度是程序运行所以需要的额外消耗存储空间,也用o()来表示比如插入排序的时间复杂度是o(n

2

),空间复杂度是o(1)而一般的递归算法就要有o(n)的空间复杂度了,因为每次递归都要存储返回信息一个算法的优劣主要从算法的执行时间和所需要占用的存储空间两个方面衡量,算法执行时间的度量不是采用算法执行的绝对时间来计算的,因为一个算法在不同的机器上执行所花的时间不一样,在不同时刻也会由于计算机资源占用情况的不同,使得算法在同一台计算机上执行的时间也不一样,所以对于算法的时间复杂性,采用算法执行过程中其基本操作的执行次数,称为计算量来度量。算法中基本操作的执行次数一般是与问题规模有关的,对于结点个数为n的数据处理问题,用T(n)表示算法基本操作的执行次数.在评价算法的时间复杂性时,不考虑两算法执行次数之间的细小区别,而只关心算法的本质差别:为此,引入一个所谓的O() 记号,则T1(n)=2n=O(n),T2(n)=n+1=O(n)。一个函数f(n)是O(g(n))的,则一定存在正常数c和m,使对所有的n>m,都满足f(n)<c*g(n)。

转载于:https://www.cnblogs.com/yinfj/p/7126643.html

算法的性能评价------空间复杂度和时间复杂度相关推荐

  1. JAVA数据结构和算法:第一章(时间复杂度和空间复杂度)

    数据结构 数据结构基础概念 不论是哪所大学,数据结构和算法这门课都被贯上无趣.犯困.困难的标签,我们从最基础最通俗的语言去说起,保证通俗易懂. 数据结构到底是什么呢?我们先来谈谈什么叫数据. 数据:数 ...

  2. 算法简介——二分查找,时间复杂度,空间复杂度

    文章目录 前言 二分查找 时间复杂度 大O表示法 空间复杂度 小结 前言 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略 ...

  3. Algorithm Master Road:算法的时间/空间复杂度

    很多同学都觉得算法很难,难以入门,难以理解,更难以掌握和运用,其实归根溯源,我们可以把所有的问题都通过枚举法来解决,但是受困于「时间」和「空间」的因素,有的时候并不能枚举所有的情况,所以需要通过精妙的 ...

  4. 算法及时间/空间复杂度的分析

    算法(Algorithm) 对特定问题求解步骤的一种描述,是为解决一个或一类问题给出的一个确定的.有限长的操作序列 算法的基本特征 ①输入:有零个或多个输入 ②输出:有一个或多个输出 ③有穷性:在执行 ...

  5. 数据结构与算法的时间空间复杂度

    提到数据结构与算法就不得不提时间复杂度和空间复杂度,本人看大部分文章介绍都比较晦涩难懂,就想着用简单的代码示例快速让你理解数据结构与算法的时间空间复杂度. 首先,时间复杂度表示的是使用某个数据结构或者 ...

  6. 排序算法 之希尔排序及时间复杂度分析

    排序算法之 冒泡排序及性能优化(时间复杂度+空间复杂度分析) 排序算法之 简单选择排序及时间复杂度分析 排序算法之 直接插入排序及时间复杂度分析 希尔排序 算法思想:将整个待排序列分割成若干个子序列( ...

  7. 排序--Bubble的优化和性能(算法时间、空间复杂度、稳定性)分析

    一.算法基本思想 (1)基本思想 冒泡排序的基本思想就是:从无序序列头部开始,进行两两比较,根据大小交换位置,直到最后将最大(小)的数据元素交换到了无序队列的队尾,从而成为有序序列的一部分:下一次继续 ...

  8. 数据结构与算法 1.算法与数据结构的关系,以及算法时间、空间复杂度的概 念及其度量方法

    文章目录 前言 一. 数据结构 1.1 概念: 1.2 数据结构分类(逻辑结构和物理结构两大类) 1.2.1 逻辑结构 1.2.2 物理结构 二. 算法 2.1 概念 2.2 算法初体验 2.3 算法 ...

  9. 【算法复杂度——空间复杂度-Python】算法空间复杂度的详细介绍

    空间复杂度 概念定义 指令空间: 数据空间: 栈帧空间: 符号表示 常见种类 示例解析 常数*O*(1): 线性*O*(*N*) 平方*O*(*N*^2^): 指数*O*(2^N^) : 对数*O*( ...

最新文章

  1. 太形象!打工人入职前后的心理变化 | 每日趣闻
  2. MySQL的系统数据库是_mysql数据库系统
  3. 【Groovy】map 集合 ( map 集合遍历 | 使用 map 集合的 find 方法遍历 map 集合 | 代码示例 )
  4. Sratch-gui 中文文档
  5. 射影几何3:拓广平面
  6. KDDockWidgets源码编译及安装
  7. SAP UI5 调试模式标志位的持久化原理 - local storage
  8. 判断微信小游戏用户是否真的分享
  9. JavaScript应用(重点数组)
  10. Flash与组件:制作Slider组件
  11. 28线性空间02——坐标、坐标变换与基变换、过度矩阵
  12. excel实时获取基金信息的实现方法
  13. ai人工智能操控什么意思_为什么要建立AI分散式自治组织(AI DAO)
  14. 针对百度的常规网页优化策略
  15. 血与泪的教训: JavaWeb中文乱码问题整合
  16. 推荐几个可以免费使用的ChatGPT工具
  17. 圆面积计算公式,这样理解起来超简单!
  18. 将一根木棍分成三段,求这三段构成三角形的概率
  19. 获取手机通讯录加好友
  20. 如何批量将word转换成pdf?

热门文章

  1. MongoDB基本概念学习 - 集合
  2. 多核 CPU 和多个 CPU 有何区别
  3. 图解Oracle 12c 触发器实例
  4. redis学习(七)jedis客户端
  5. 内核打上yaffs2补丁遇到的问题
  6. Struts2 拦截器 及如何获得 servlet 请求对象 以及Struts 基本配置 Session 超时设置...
  7. C#开发WPF/Silverlight动画及游戏系列教程(Game Tutorial):(二十五)完美捕捉精灵之神器 -- HitTest...
  8. 10kv开关柜价格_什么是10KV开闭所,开闭所主要是什么作用?一起来探个究竟
  9. mysql悲观锁只用于读取吗_MySQL中悲观锁和乐观锁到底是什么?
  10. 【STM32】位操作、按位与、按位或、按位异或、取反、左移、右移等基础 C 语言知识补充