时间复杂度和空间复杂度1

让编程改变世界

Change the world by program


算法效率的度量方法

上一讲中我们提到设计算法要尽量的提高效率,这里效率高一般指的是算法的执行时间。 那么我们如何来度量一个算法的执行时间呢?   所谓“是骡子是马拉出来遛遛”,比较容易想到的方法就是我们把算法跑若干次,然后拿个“计时器”在旁边计时。 这种事后统计方法看上去的确不错,并且也并非真的要你拿个计算器在那里计算,因为计算机都有计时功能。   事后统计方法:这种方法主要是通过设计好的测试程序和数据,利用计算机计时器对不同算法编制的程序的运行时间进行比较,从而确定算法效率的高低。

但这种方法显然是有很大缺陷的:

  1. 必须依据算法事先编制好测试程序,通常需要花费大量时间和精力,完了发觉测试的是糟糕的算法,那不是功亏一篑?赔了娘子又折兵?
  2. 不同测试环境差别不是一般的大!

我们把刚刚的估算方法称为事后诸葛亮。 我们的计算机前辈们也不一定知道诸葛亮是谁,为了对算法的评判更为科学和便捷,他们研究出事前分析估算的方法。   事前分析估算方法:在计算机程序编写前,依据统计方法对算法进行估算。   经过总结,我们发现一个高级语言编写的程序在计算机上运行时所消耗的时间取决于下列因素: 1. 算法采用的策略,方案 2. 编译产生的代码质量 3. 问题的输入规模 4. 机器执行指令的速度   由此可见,抛开这些与计算机硬件、软件有关的因素,一个程序的运行时间依赖于算法的好坏和问题的输入规模。(所谓的问题输入规模是指输入量的多少)   我们搬回搞死先生的那个算法来跟大家谈谈: 第一种算法: [codesyntax lang="c"]

int i, sum = 0, n = 100;   // 执行1次
for( i=1; i <= n; i++ )    // 执行了n+1次
{sum = sum + i;         // 执行n次
}

[/codesyntax]   第二种算法: [codesyntax lang="c"]

int sum = 0, n = 100;     // 执行1次
sum = (1+n)*n/2;          // 执行1次

[/codesyntax]   第一种算法执行了1+(n+1)+n=2n+2次。 第二种算法,是1+1=2次   如果我们把循环看做一个整体,忽略头尾判断的开销,那么这两个算法其实就是n和1的差距。 有些喜欢跟真理死磕的朋友可能对小甲鱼这观点意见不是一般的大! 因为循环判断在算法1里边执行了n+1次,看起来是个不小的数量,凭什么说忽略就能忽略?   淡定,请接着继续看延伸的例子: [codesyntax lang="c"]

int i, j, x=0, sum=0, n=100;
for( i=1; i <= n; i++ )
{for( j=1; j <= n; j++ ){x++;sum = sum + x;}
}

[/codesyntax]     这个例子中,循环条件i从1到100,每次都要让j循环100次,如果非常较真的研究总共精确执行次数,那是非常累的。 另一方面,我们研究算法的复杂度,侧重的是研究算法随着输入规模扩大增长量的一个抽象,而不是精确地定位需要执行多少次。   因为如果这样的话,我们就又得考虑回编译器优化等问题,然后,然后就永远也没有然后了! 所以,对于刚才例子的算法,我们可以果断判定需要执行100^2次。   我们不关心编写程序所用的语言是什么,也不关心这些程序将跑在什么样的计算机上,我们只关心它所实现的算法。 这样,不计那些循环索引的递增和循环终止条件、变量声明、打印结果等操作。   最终,在分析程序的运行时间时,最重要的是把程序看成是独立于程序设计语言的算法或一系列步骤。 我们在分析一个算法的运行时间时,重要的是把基本操作的数量和输入模式关联起来。 [caption id="attachment_688" align="aligncenter" width="493"] 算法效率的度量方法[/caption]

函数的渐近增长

小甲鱼给大家做一个测试:判断以下两个算法A和B哪个更好? 假设两个算法的输入规模都是n,算法A要做2n+3次操作,你可以这么理解:先执行n次的循环,执行完成后再有一个n次的循环,最后有3次运算。 算法B要做3n+1次操作,理解同上,你觉得它们哪一个更快些呢?   在给大家解答问题之前,小甲鱼先给大家做个图表参考: [caption id="attachment_689" align="aligncenter" width="600"] 函数的渐近增长[/caption]   当n=1时,算法A1效率不如算法B1,当n=2时,两者效率相同; 当n>2时,算法A1就开始优于算法B1了,随着n的继续增加,算法A1比算法B1逐步拉大差距。 所以总体上算法A1比算法B1优秀。 [caption id="attachment_690" align="aligncenter" width="523"] 函数的渐近增长[/caption]   函数的渐近增长:给定两个函数f(n)和g(n),如果存在一个整数N,使得对于所有的n>N,f(n)总是比g(n)大。 那么,我们说f(n)的增长渐近快于g(n)。     从刚才的对比中我们还发现,随着n的增大,后面的+3和+1其实是不影响最终的算法变化曲线的。 例如算法A2,B2,在图中他们压根儿被覆盖了。所以,我们可以忽略这些加法常数。   后边我们给大家举多几个例子,会更明显。 第二个测试,算法C是4n+8,算法D是2n^2+1。 [caption id="attachment_691" align="aligncenter" width="600"] 函数的渐近增长[/caption]   再来看一下线性图。 [caption id="attachment_692" align="aligncenter" width="495"] 函数的渐近增长[/caption]   我们观察发现,哪怕去掉与n相乘的常数,两者的结果还是没有改变,算法C2的次数随着n的增长,还是远小于算法D2。 也就是说,与最高次项相乘的常数并不重要,也可以忽略。   我们再来看第三个测试,算法E是2n^2+3n+1,算法F是2n^3+3n+1。 [caption id="attachment_693" align="aligncenter" width="600"] 函数的渐近增长[/caption]   再来看一下线性图。 [caption id="attachment_694" align="aligncenter" width="515"] 函数的渐近增长[/caption]     这次我们又发现什么呢? 小甲鱼没有小鸡鸡?   不是的,我们通过观察又发现,最高次项的指数大的,函数随着n的增长,结果也会变得增长特别快。 恩,我们进行最后一个小测试,把这些概念都总结起来吧!   算法G是2n^2,算法H是3n+1,算法I是 2n^+3n+1。 [caption id="attachment_695" align="aligncenter" width="600"] 函数的渐近增长[/caption]   [caption id="attachment_696" align="aligncenter" width="652"] 函数的渐近增长[/caption]   看出啥?一条直线?当他们数据很小的时候是这样的: [caption id="attachment_697" align="aligncenter" width="493"] 函数的渐近增长[/caption]   这组数据我们看得很清楚,当n的值变得非常大的时候,3n+1已经没法和2n^2的结果相比较,最终几乎可以忽略不计。 而算法G在跟算法I基本已经重合了。 于是我们可以得到这样一个结论,判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,而更应该关注主项(最高项)的阶数。 注意,判断一个算法好不好,我们只通过少量的数据是不能做出准确判断的,很容易以偏概全。 [buy] 获得所有教学视频、课件、源代码等资源打包 [/buy] [Downlink href='http://kuai.xunlei.com/d/LFXEKOXZQTCW']视频下载[/Downlink] [Downlink href='http://urlxf.qq.com/?Eb6Zj2i']备胎下载[/Downlink]

转载于:https://www.cnblogs.com/LoveFishC/archive/2012/09/04/3846248.html

时间复杂度和空间复杂度1 - 数据结构和算法03相关推荐

  1. 时间复杂度和空间复杂度3 - 数据结构和算法05

    时间复杂度和空间复杂度3 让编程改变世界 Change the world by program 函数调用的时间复杂度分析 如果我们把问题再实际化一点,大家是否能自己正确的分析出来呢? 我们来看下边这 ...

  2. 研磨数据结构与算法-03栈与队列

    一,栈 public class MyStack { //底层实现是一个数组 private long[] arr; private int top; /** * 默认的构造方法 */ public ...

  3. 数据结构与算法 -- 时间复杂度

    数据结构与算法看完了,回过头来在看时间复杂度,对它们的效率做个比较吧. 一.时间复杂度介绍 1.时间复杂度定义 参看:数据结构-算法-时间复杂度计算 在进行算法分析,语句总得执行次数 T(n) 是关于 ...

  4. day001:数据结构和算法-时间频度和时间复杂度

    1.初识数据结构和算法 简单认识中:ArrayList的查询快点,插入慢.LinkedList查询慢,插入快.但是结论是将数据的大小为基础前提,相对的. -1^n 计算问题 编程问题:求(-1)^0 ...

  5. 算法:算法概述【时间复杂度、空间复杂度】

    一.算法定义 算法:为了实现业务目的的各种方法和思路就是算法.同样的数据,同样的目的, 不同的算法,不同的方法和思路,效率就会不同 算法是一种独立的存在 , 它并不依附于代码 , 代码只是实现算法思想 ...

  6. 时间复杂度和空间复杂度计算(数据结构C语言实现1)

    写在前面 数据结构C语言系列,和博主一起学习简单的数据结构和算法,都是利用C语言实现,很基础,相信大家都能够学会,都有所收获.记得点赞,收获. 目录 写在前面 本节目标 基本概念 **常见算法的时间复 ...

  7. 【数据结构】时间复杂度和空间复杂度

    文章目录 前言 1. 什么是数据结构 2. 什么是算法 正文 1. 算法效率 1.1 如何衡量一个算法的优劣 1.2 算法的复杂度 2. 时间复杂度 2.1 定义 2.2 计算 2.3 大O的渐进表示 ...

  8. 关于算法的时间复杂度和空间复杂度的总结

    一.算法的概念   算法(Algorithm)是将一组输入转化为一组输出的一系列计算步骤,其中每个步骤必须能在有限时间内完成.算法是用来解决一类计算问题的,注意是一类问题,而不是一个特定的问题. 二. ...

  9. <时间复杂度和空间复杂度计算>《数据结构(C语言版)》

    人总得接受平凡和遗憾,但那不是一直自甘堕落的理由.显贵出身也好,泥腿子出身也罢,人生一世,你不仅为自己而活,你还承担着家族崛起的使命,是承上启下的一代,往大了说,也是国家.社会的一份子,总得做些有意义 ...

  10. 数据结构(算法空间复杂度)

    目录 造成算法空间复杂度的因素 实例 对于时间复杂度和空间复杂度的理解 造成算法空间复杂度的因素 算法的空间消耗包括三个方面: Ø实现算法的程序本身需要占据存储空间 Ø待处理的数据需要在内存中存储,占 ...

最新文章

  1. php处理微信返回xml数据,php将微信返回的xml格式转换成数组
  2. 这是你从未见过的组件库 -- Android 上的手绘风格组件
  3. linux 常用头文件,(常用头文件详解.doc
  4. 通过socket得到远端的IP和连接端口
  5. python 单链表查找元素_如何在python中一次找到链表的中间元素?
  6. 服务自动拉起,定时日志清理,数据统计的shell脚本
  7. Flash cs4 for mac 序列号
  8. 一起学爬虫(Python) — 21 蝉妈妈,嘿嘿
  9. 高质量解读《互联网企业安全高级指南》——目录
  10. 电脑使用小常识(4):让win10强制更新棍淡
  11. no moudle named dlib
  12. Mockito开发指南
  13. haproxy path_beg,path_end ,hdr_beg
  14. python获取控件内容_python通过win32api轻松获取控件的属性值
  15. Markdown格式文档图片设置居中
  16. 关于GPU一些笔记(SIMT方面)
  17. 剑灵力士卡刀ahk_[游戏]剑灵剑士火系卡刀
  18. 非居民账户(NRA)和OSA
  19. 【C语言进阶】⑦字符串函数详解
  20. ffmpeg 编码 png apng图片

热门文章

  1. json_decode 打印 null
  2. python如何定义一个空列表1s_如何在Python中创建多个(但单独的)空列表?
  3. JAVA转为wasm/JavaScript,可以考虑CheerpJ
  4. 编码基本功:给刚刚学习编程的朋友的建议
  5. java.library.path设置无效
  6. 回忆有自己的场景,有两种角度
  7. TensorRT同时加载多个模型很容易崩溃
  8. 听通灵人说自己的感悟
  9. JSON的C代码示例
  10. 实现模拟内存动态分区分配算法_你还在为了JVM而烦恼么?(内存结构和垃圾回收算法)...