原文地址:http://learn.akae.cn/media/ch11s03.html

解决同一个问题可以有很多种算法,比较评价算法的好坏,一个重要的标准就是算法的时间复杂度。现在研究一下插入排序算法的执行时间,按照习惯,输入长度LEN以下用n表示。假设循环中各条语句的执行时间分别是c1、c2、c3、c4、c5这样五个常数[20]:

void insertion_sort(void)   执行时间
{
 int i, j, key;
 for (j = 1; j < LEN; j++) {
  key = a[j];   c1
  i = j - 1;   c2
  while (i >= 0 && a[i] > key) {
   a[i+1] = a[i];  c3
   i--;   c4
  }
  a[i+1] = key;   c5
 }
}

显 然外层for循环执行次数是n-1次,假设内层的while循环执行m次,则总的执行时间粗略估计是(n-1)*(c1+c2+c5+m* (c3+c4))。当然,for和while后面()括号中的赋值和条件判断也需要时间,而我没有设一个常数来表示,这不影响我们的粗略估计。

这 里有一个问题,m不是个常数,也不取决于输入长度n,而是取决于具体的输入数据。在最好情况下,数组a的原始数据已经排好序了,while循环一次也不执 行,总的执行时间是(c1+c2+c5)*n-(c1+c2+c5),可以表示成an+b的形式,是n的线性函数(Linear Function)。那么在最坏情况(Worst Case)下又如何呢?所谓最坏情况是指数组a的原始数据正好是从大到小排好序的,请读者想一想为什么这是最坏情况,然后把上式中的m替换掉算一下执行时间是多少。

数组a的原始数据属于最好和最坏情况都比较少见,如果原始数据是随机的,可称为平均情况(Average Case)。 如果原始数据是随机的,那么每次循环将已排序的子序列a[1..j-1]与新插入的元素key相比较,子序列中平均都有一半的元素比key大而另一半比 key小,请读者把上式中的m替换掉算一下执行时间是多少。最后的结论是:在最坏情况和平均情况下,总的执行时间都可以表示成an2+bn+c的形式,是n的二次函数(Quadratic Function)。

在分析算法的时间复杂度时,我们更关心最坏情况而不是最好情况,理由如下:

1.

最坏情况给出了算法执行时间的上界,我们可以确信,无论给什么输入,算法的执行时间不会超过这个上界,为比较和分析提供了便利。
   2.

对于某些算法,最坏情况是最常发生的情况,例如在数据库中查找某个信息的算法,最坏情况就是数据库中根本不存在该信息,都找遍了也没有,而某些应用场合经常要查找一个信息在数据库中存在不存在。
   3.

虽然最坏情况是一种悲观估计,但是对于很多问题,平均情况和最坏情况的时间复杂度差不多,比如插入排序这个例子,平均情况和最坏情况的时间复杂度都是输入长度n的二次函数。

比较两个多项式a1n+b1和a2n2+b2n+c2的值(n取正整数)可以得出结论:n的最高次指数是最主要的决定因素,常数项、低次幂项和系数都是次要的。比如100n+1和n2+1, 虽然后者的系数小,当n较小时前者的值较大,但是当n>100时,后者的值就远远大于前者了。如果同一个问题可以用两种算法解决,其中一种算法的时 间复杂度为线性函数,另一种算法的时间复杂度为二次函数,当问题的输入长度n足够大时,前者明显优于后者。因此我们可以用一种更粗略的方式表示算法的时间 复杂度,把系数和低次幂项都省去,线性函数记作Θ(n),二次函数记作Θ(n2)。

Θ(g(n))表示和g(n)同一量级的一类函数,例如所有的二次函数f(n)都和g(n)=n2属于同一量级,都可以用Θ(n2)来表示,甚至有些不是二次函数的也和n2属于同一量级,例如2n2+3lgn。“同一量级”这个概念可以用下图来说明(该图出自[算法导论]):

图 11.2. Θ-notation
Θ-notation

如果可以找到两个正的常数c1和c2,使得n足够大的时候(也就是n≥n0的时候)f(n)总是夹在c1g(n)和c2g(n)之间,就说f(n)和g(n)是同一量级的,f(n)就可以用Θ(g(n))来表示。

以二次函数为例,比如1/2n2-3n,要证明它是属于Θ(n2)这个集合的,我们必须确定c1、c2和n0,这些常数不随n而改变,并且当n≥n0以后,c1n2≤1/2n2-3n≤c2n2总是成立的。为此我们从不等式的每一边都除以n2,得到c1≤1/2-3/n≤c2。见下图:

图 11.3. 1/2-3/n
1/2-3/n

这样就很容易看出来,无论n取多少,该函数一定小于1/2,因此c2=1/2,当n=6时函数值为0,n>6时该函数都大于0,可以取n0=7,c1=1/14,这样当n≥n0时都有1/2-3/n≥c1。通过这个证明过程可以得出结论,当n足够大时任何an2+bn+c都夹在c1n2和c2n2之间,相对于n2项来说bn+c的影响可以忽略,a可以通过选取合适的c1、c2来补偿。

几种常见的时间复杂度函数按数量级从小到大的顺序依次是:Θ(lgn),Θ(sqrt(n)),Θ(n),Θ(nlgn),Θ(n2),Θ(n3),Θ(2n),Θ(n!)。其中,lgn通常表示以10为底n的对数,但是对于Θ-notation来说,Θ(lgn)和Θ(log2n) 并无区别(想一想这是为什么),在算法分析中lgn通常表示以2为底n的对数。可是什么算法的时间复杂度里会出现lgn呢?回顾插入排序的时间复杂度分 析,无非是循环体的执行时间乘以循环次数,只有加和乘运算,怎么会出来lg呢?下一节归并排序的时间复杂度里面就有lg,请读者留心lg运算是从哪出来 的。

除了Θ-notation之外,表示算法的时间复杂度常用的还有一种Big-O notation。我们知道插入排序在最坏情况和平均情况下时间复杂度是Θ(n2),在最好情况下是Θ(n),数量级比Θ(n2)要小,那么总结起来在各种情况下插入排序的时间复杂度是O(n2)。Θ的含义和“等于”类似,而大O的含义和“小于等于”类似。

[20] 受计算机内存管理机制的影响,指令的执行时间不一定是常数,但执行时间的上界(Upper Bound)肯定是常数,我们这里假设语句的执行时间是常数只是一个粗略估计。

算法时间复杂度Θ(n2)与 O(n2)相关推荐

  1. C++实现十大排序算法(冒泡,选择,插入,归并,快速,堆,希尔,桶,计数,基数)排序算法时间复杂度、空间复杂度、稳定性比较(面试经验总结)

    排序算法分类 内部排序算法又分为基于比较的排序算法和不基于比较的排序算法,其分类如下: 比较排序:   直接插入排序    希尔排序 (插入)  冒泡排序     快速排序  (交换) 直接选择排序  ...

  2. 排序算法 时间复杂度+空间复杂度 总结

    辅助记忆 时间复杂度记忆: 冒泡.选择.直接 排序需要两个for循环,每次只关注一个元素,平均时间复杂度为O(n2)O(n2)(一遍找元素O(n)O(n),一遍找位置O(n)O(n)) 快速.归并.希 ...

  3. 算法时间复杂度lg是多少_算法时间复杂度空间复杂度(附github)

    (*useful)标记:目前觉得有用的函数 //FIXME 标记:待补充 基本初等函数: 幂函数: 一般地,形如y=xα(α为有理数)的函数,即以底数为自变量,幂为因变量,指数为常数的函数称为幂函数. ...

  4. 算法积累之算法时间复杂度

    算法时间复杂度是对算法效率的重要衡量标准. 人们说的事前分析估算算法效率,就是对算法时间复杂度的计算.我在看书过程中的一些小误解.在此记录. 举例. int sum = 0,n = 100; sum ...

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

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

  6. 大话数据结构之算法 时间复杂度

    http://www.cnblogs.com/danyingjie/archive/2011/11/17/2252466.html 时间复杂度用O()来体现,我们称之为大O记法.记做:T(n)=O(f ...

  7. 排序算法时间复杂度、空间复杂度、稳定性比较

    排序算法分类 排序算法比较表格填空 排序算法 平均时间复杂度 最坏时间复杂度 空间复杂度 是否稳定 冒泡排序 :-----: :-–: :-–: :-–: 选择排序 :-----: :-–: :-–: ...

  8. 算法时间复杂度计算方法

    一.概念: 时间复杂度是总运算次数表达式中受n的变化影响最大的那一项(不含系数) 比如:一般总运算次数表达式类似于这样: a*2^n+b*n^3+c*n^2+d*n*lg(n)+e*n+f a ! = ...

  9. 算法-时间复杂度和空间复杂度

    2.9 算法时间复杂度 2.9.1 算法时间复杂度定义 在进行算法分析时 , 语句总的执行次数 T ( n )是关子问题规模n的函数,进而分析 T ( n )随 n 的变化情况并确定T(n)的数量级. ...

  10. Java数据结构(1.1):数据结构入门+线性表、算法时间复杂度与空间复杂度、线性表、顺序表、单双链表实现、Java线性表、栈、队列、Java栈与队列。

    数据结构与算法入门 问题1:为什么要学习数据结构          如果说学习语文的最终目的是写小说的话,那么能不能在识字.组词.造句后就直接写小说了,肯定是不行的, 中间还有一个必经的阶段:就是写作 ...

最新文章

  1. 微信小程序左滑删除效果的实现完整源码附效果图
  2. lin通信ldf文件解析_详细步骤讲解如何在CANoe中创建一个LIN通讯工程(多图+详解)...
  3. 高等数学上-赵立军-北京大学出版社-题解-练习4.5
  4. JS中的数据类型转换
  5. Qt工作笔记-自定义打印及存日志及stderr转stdout(Linux程序调试技巧,提高开发效率)
  6. 使用RPM安装Mysql5.5找不到配置文件My.cnf
  7. Vegas轻松get制作动态背景技能
  8. 打包 pyqt5_基于Pyqt5的简单电影搜索工具,Python让你3秒搜电影
  9. 前端开源实战项目推荐
  10. Resnet18详细结构
  11. 百度不收录网站的原因
  12. javascript/js 判断是否安装flash player插件,提示安装方法。
  13. 什么是大数据开发?看完我终于懂了......
  14. winform 中listBox控件绑定list类型数据源,并设置DisplayMember
  15. python leetcode 387. First Unique Character in a String
  16. 判断用户输入的字母大小写C语言+if语句的初级学习
  17. SpringCloud 实战笔记
  18. AU2009大会介绍附课程名称
  19. JavaScript 控制台打印window对象
  20. 提取MATLAB fig的数据

热门文章

  1. 利用adsl拨号服务器VPS构建代理IP池
  2. 彰显互联网基因:大数据引发互联网原创综艺革新。。
  3. 冰点还原忘记密码如何修改配置或卸载
  4. 雷尼绍Renishaw wdf 文件解析(Python源码)软件分享
  5. 设计模式的艺术 结构性模式之组合模式
  6. 黑马程序员——多态和抽象类的相关知识
  7. php性格属于哪类,狗狗性格分为6大类,你家是属哪一类?快来是看聪明型还是粘人型...
  8. emlog5.3.1后台暴力破解
  9. git-ftp 用git管理ftp空间
  10. 在word中插入分页符,多出一行