通常,要分析的最重要的资源就是运行时间。有几个因素影响着程序的运行时间。有些因素(如使用编译器和计算机)显然超出了任何理论模型的范畴,因此,虽然它们是重要的,但是我们在这里还是不能考虑它们。剩下的主要因素是所使用的算法以及对该算法的输入。

典型的情形是,输入的大小是主要的考虑方面。我们定义两个函数Tavg(N)和Tworst(N),分别为算法对于输入量N所花费的平均运行时间和最坏情况的运行时间。显然,Tavg(N)<=Tworst(N)。

如果存在多于一个的输入,那么这些函数可用有多于一个的变量。

偶尔也分析一个算法的最好情形的性能。不过,通常这没有什么重要意义,因为它不代表典型的行为。平均情形性能常常反映典型的行为,而最坏的性能则代表对任何可能输入的性能一种保证。还要注意,虽然在这一章我们分析的是Java程序,但所得到的界实际上是算法的界而不是程序的界。程序是算法以一种特殊编程语言的实现,程序设计语言的细节几乎总是不影响大于O的答案。如果一个程序比算法分析提出的速度慢得多,那么可能存在低效率的实现。这在类似C++的语言中很普遍,比如,数组可能当作整体而被漫不经心的拷贝,而不是由引用来传递。不管怎么说,这在Java中也可能出现。

一般来说,如果没有相反的指定,则所需要的量是最坏情况的运行时间。其原因之一是它对所有的输入提供了一个界限,包括特别坏的输入,而平均情况分析不提供这样的界。另一个原因是平均情况的界计算起来通常要困难得多。在某些情况下,“平均”的定义可能影响分析的结果。(例如,什么是下属问题的平均输入?)

作为一个例子,我们将在下一节考虑下述问题:

最大子序列和问题:

例如:对于输入-2,11,-4,13,-5,-2,答案为20(从A2到A4) 。

这个问题之所以有吸引力,主要是因为存在求解它的很多算法,而这些算法的性能又差异很大。我们将讨论求解该问题的四种算法。这四种算法在某台计算机上(究竟是哪一台具体的计算机并不重要)的运行时间。如图:

在表中有几个重要的情况值得注意。对于小量的输入,这些算法都在眨眼之间完成,因此如果只是小量输入的情形,那么花费大量的努力去设计聪明的算法恐怕就太不值得了。

另一方面,近来对于重写那些不再合理的基于小输入量假设而在五年以前编写的程序确实存在巨大的市场。现在看来,这些程序太慢了,因为它们用的是一些低劣的算法。对于大量的输入,算法4显然是最好的选择(虽然算法3也可以用)。

其次,表中所给的时间不包括读入数据所需要的时间。对于算法4,仅仅从磁盘读入数据所用的时间很可能在数量级上比求解上述问题所需要的时间还要大。这是许多有效算法的典型特点。数据的读入一般是个瓶颈;一旦数据读入,问题就会迅速解决。但是,对于低效率的算法情况就不同了,它必然要占用大量的计算机资源。因此只要可能,使得算法足够有效而不至成为问题的瓶颈是非常重要的。

注意到具有线性复杂度的算法4表现很好,当问题的规模增长了十倍的时候,其运行的时间也增长十倍。而具有平方复杂度的算法2就不行了,十倍的规模增长导致运行时间大于有百倍(10的2次方)的增长。而立方级复杂度的算法1的运行时间则由千倍(10的3次方)的增长。对于N=100000,我们可以预期算法1将花费近乎90000秒或一天的时间。类似地,我们可预期算法2用大约333秒来完成N=1000000。然而,算法2也可能花费更多的时间,因为在现代计算机中,内存存取N=1000000可能比处理N=100000要慢,这取决于内存缓存的大小。

再看图:

左图指出了四种算法运行时间的增长率。尽管该图只包含N从10到100的值,但是相对增长率还是很明显的。虽然O(NlogN)算法的图看起来是线性的,但是用直尺的边(或是一张纸)容易验证它并不是直线。虽然O(N)算法的图看似直线,但这只是因为对于小的N值其中的常数项大于线性项。右图中更显示对于更大值的性能。该图明显地表明,对于即使是适度大小的输入量低效算法依然是多么的无用。

<数据结构与算法分析>读书笔记--要分析的问题的更多相关文章

  1. <数据结构与算法分析>读书笔记--最大子序列和问题的求解

    现在我们将要叙述四个算法来求解早先提出的最大子序列和问题. 第一个算法,它只是穷举式地尝试所有的可能.for循环中的循环变量反映了Java中数组从0开始而不是从1开始这样一个事实.还有,本算法并不计算 ...

  2. <数据结构与算法分析>读书笔记--运行时间计算

    有几种方法估计一个程序的运行时间.前面的表是凭经验得到的(可以参考:<数据结构与算法分析>读书笔记--要分析的问题) 如果认为两个程序花费大致相同的时间,要确定哪个程序更快的最好方法很可能 ...

  3. <数据结构与算法分析>读书笔记--函数对象

    关于函数对象,百度百科对它是这样定义的: 重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象.又称仿函数. 听起来确实很难懂,通过搜索我找到一篇 ...

  4. <数据结构与算法分析>读书笔记--利用Java5泛型实现泛型构件

    一.简单的泛型类和接口 当指定一个泛型类时,类的声明则包括一个或多个类型参数,这些参数被放入在类名后面的一对尖括号内. 示例一: package cn.generic.example; public ...

  5. <数据结构与算法分析>读书笔记--数学知识复习

    数学知识复习是<数据结构与算法分析>的第一章引论的第二小节,之所以放在后面,是因为我对数学确实有些恐惧感.不过再怎么恐惧也是要面对的. 一.指数 基本公式: 二.对数 在计算机科学中除非有 ...

  6. <数据结构与算法分析>读书笔记--运行时间中的对数及其分析结果的准确性

    分析算法最混乱的方面大概集中在对数上面.我们已经看到,某些分治算法将以O(N log N)时间运行.此外,对数最常出现的规律可概括为下列一般法则: 如果一个算法用常数时间(O(1))将问题的大小削减为 ...

  7. <数据结构与算法分析>读书笔记--模型

    为了在正式的构架中分析算法,我们需要一个计算模型.我们的模型基本上是一台标准的计算机,在机器中指令被顺序地执行.该模型有一个标准的简单指令系统,如加法.乘法.比较和赋值等.但不同于实际计算机情况的是, ...

  8. <数据结构与算法分析>读书笔记--实现泛型构件pre-Java5

    面向对象的一个重要目标是对代码重用的支持.支持这个目标的一个重要的机制就是泛型机制:如果除去对象的基本类型外,实现的方法是相同的,那么我们就可以用泛型实现来描述这种基本的功能. 1.使用Object表 ...

  9. <数据结构与算法分析>读书笔记--递归

    一.什么是递归 程序调用自身的编程技巧称为递归( recursion).递归做为一种算法在程序设计语言中广泛应用. 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的 ...

随机推荐

  1. [android] 手机卫士绑定sim卡

    更新: 收不到启动广播,查看知乎,好像是说高版本的系统都禁止了 还可以通过adb发送开机广播 adb shell am broadcast -a android.intent.action.BOOT_ ...

  2. Java-关于类

    java-关于类-成员初始化问题 成员初始化出现错误“    - Syntax error on token ";", , expected” java类不允许对成员进行操作,但可 ...

  3. SPOJ GSS3 (动态dp)

    题意 题目链接 Sol 这题可以动态dp做. 设\(f[i]\)表示以\(i\)为结尾的最大子段和,\(g[i]\)表示\(1-i\)的最大子段和 那么 \(f[i] = max(f[i - 1] + ...

  4. 2017 SCNUCPC 解题报告

    校内赛题目.解题思路.参考代码一览 A. Blackstorm's Blackstore Problem Description Blackstorm is going to open a black ...

  5. vue-cli脚手架之build文件夹上半部

    好,接下来一起分析分析配置文件^o^. build.js作用:命令npm run build的入口配置文件,主要用于生产环境. build.js中具体含义标注(vue-cli脚手架官方文件解释,大家可 ...

  6. TCP协议学习总结

    1.TCP协议通过三次握手建连接,四次挥手断连接. 2.TCP的定时器都有哪些? 做什么用途? 3.TCP的慢启动是什么意思? 4.TCP的快速重传是什么意思?

  7. Android系统启动流程(一)解析init进程启动过程

    整体流程大致如下:     1.init简介 init进程是Android系统中用户空间的第一个进程,作为第一个进程,它被赋予了很多极其重要的工作职责,比如创建zygote(孵化器)和属性服务等.in ...

  8. Flume Source 实例

    Flume Source 实例 Avro Source 监听avro端口,接收外部avro客户端数据流.跟前面的agent的Avro Sink可以组成多层拓扑结构. 1 2 3 4 5 6 7 8 9 ...

  9. C#检测U盘是否插入

    public partial class Form1 : Form { #region u盘属性 public const int WM_DEVICECHANGE = 0x219;//U盘插入后,OS ...

  10. Android 发送自定义广播(标准和本地)

    1.首先自定义一个广播接收器:MyBroadcastReceiver package example.com.mybroadcastreceiver; import android.content.B ...