算法的时间复杂性

合集下载

算法的时间复杂度和空间复杂度-总结分析

算法的时间复杂度和空间复杂度-总结分析

算法的时间复杂度和空间复杂度-总结通常,对于一个给定的算法,我们要做两项分析。

第一是从数学上证明算法的正确性,这一步主要用到形式化证明的方法及相关推理模式,如循环不变式、数学归纳法等。

而在证明算法是正确的基础上,第二部就是分析算法的时间复杂度。

算法的时间复杂度反映了程序执行时间随输入规模增长而增长的量级,在很大程度上能很好反映出算法的优劣与否。

因此,作为程序员,掌握基本的算法时间复杂度分析方法是很有必要的。

算法执行时间需通过依据该算法编制的程序在计算机上运行时所消耗的时间来度量。

而度量一个程序的执行时间通常有两种方法。

一、事后统计的方法这种方法可行,但不是一个好的方法。

该方法有两个缺陷:一是要想对设计的算法的运行性能进行评测,必须先依据算法编制相应的程序并实际运行;二是所得时间的统计量依赖于计算机的硬件、软件等环境因素,有时容易掩盖算法本身的优势。

二、事前分析估算的方法因事后统计方法更多的依赖于计算机的硬件、软件等环境因素,有时容易掩盖算法本身的优劣。

因此人们常常采用事前分析估算的方法。

在编写程序前,依据统计方法对算法进行估算。

一个用高级语言编写的程序在计算机上运行时所消耗的时间取决于下列因素:(1). 算法采用的策略、方法;(2). 编译产生的代码质量;(3). 问题的输入规模;(4). 机器执行指令的速度。

一个算法是由控制结构(顺序、分支和循环3种)和原操作(指固有数据类型的操作)构成的,则算法时间取决于两者的综合效果。

为了便于比较同一个问题的不同算法,通常的做法是,从算法中选取一种对于所研究的问题(或算法类型)来说是基本操作的原操作,以该基本操作的重复执行的次数作为算法的时间量度。

1、时间复杂度(1)时间频度一个算法执行所耗费的时间,从理论上是不能算出来的,必须上机运行测试才能知道。

但我们不可能也没有必要对每个算法都上机测试,只需知道哪个算法花费的时间多,哪个算法花费的时间少就可以了。

并且一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句执行次数多,它花费时间就多。

深度优先算法和广度优先算法的时间复杂度

深度优先算法和广度优先算法的时间复杂度

深度优先算法和广度优先算法的时间复杂度深度优先算法和广度优先算法是在图论中常见的两种搜索算法,它们在解决各种问题时都有很重要的作用。

本文将以深入浅出的方式从时间复杂度的角度对这两种算法进行全面评估,并探讨它们在实际应用中的优劣势。

1. 深度优先算法的时间复杂度深度优先算法是一种用于遍历或搜索树或图的算法。

它从图中的某个顶点出发,沿着一条路径一直走到底,直到不能再前进为止,然后回溯到上一个节点,尝试走其他的路径,直到所有路径都被走过为止。

深度优先算法的时间复杂度与图的深度有关。

在最坏情况下,深度优先算法的时间复杂度为O(V+E),其中V表示顶点的数量,E表示边的数量。

2. 广度优先算法的时间复杂度广度优先算法也是一种用于遍历或搜索树或图的算法。

与深度优先算法不同的是,广度优先算法是从图的某个顶点出发,首先访问这个顶点的所有邻接节点,然后再依次访问这些节点的邻接节点,依次类推。

广度优先算法的时间复杂度与图中边的数量有关。

在最坏情况下,广度优先算法的时间复杂度为O(V+E)。

3. 深度优先算法与广度优先算法的比较从时间复杂度的角度来看,深度优先算法和广度优先算法在最坏情况下都是O(V+E),并没有明显的差异。

但从实际运行情况来看,深度优先算法和广度优先算法的性能差异是显而易见的。

在一般情况下,广度优先算法要比深度优先算法快,因为广度优先算法的搜索速度更快,且能够更快地找到最短路径。

4. 个人观点和理解在实际应用中,选择深度优先算法还是广度优先算法取决于具体的问题。

如果要找到两个节点之间的最短路径,那么广度优先算法是更好的选择;而如果要搜索整个图,那么深度优先算法可能是更好的选择。

要根据具体的问题来选择合适的算法。

5. 总结和回顾本文从时间复杂度的角度对深度优先算法和广度优先算法进行了全面评估,探讨了它们的优劣势和实际应用中的选择。

通过对两种算法的时间复杂度进行比较,可以更全面、深刻和灵活地理解深度优先算法和广度优先算法的特点和适用场景。

算法的时间复杂度是指什么

算法的时间复杂度是指什么

算法的时间复杂度是指什么时间复杂度通常用大O符号表示。

大O表示法表示算法运行时间的上界,即算法最坏情况下的运行时间。

时间复杂度可以分为几个级别,如常数时间O(1)、对数时间O(log n)、线性时间O(n)、线性对数时间O(n log n)、平方时间O(n^2)等。

这些时间复杂度级别代表了问题规模增长时算法所需时间的不同变化速度。

在分析算法的时间复杂度时,通常关注的是算法运行时间随问题规模n的增长而变化的趋势,而不关注具体的运行时间。

因此,时间复杂度是一种抽象的概念,用于比较不同算法的运行效率。

1.基本操作数计数法:通过统计算法执行的基本操作数来估计算法的时间复杂度。

基本操作就是算法中最频繁执行的操作,例如赋值、比较、加法、乘法等。

基本操作数计数法的思路是,通过对算法中的基本操作进行计数,然后选择基本操作数最大的那一部分作为算法的时间复杂度。

2.事后统计法:通过实际运行算法并统计其执行时间来估计算法的时间复杂度。

这种方法通常用于验证理论上估计的时间复杂度是否准确。

然而,事后统计法只能得到特定输入情况下的时间复杂度,不能推断出算法的一般情况下的时间复杂度。

3.算法复杂度分析法:通过对算法中各个语句进行分析,得出算法的时间复杂度。

这种方法可以用数学方法推导出时间复杂度的表达式,通常使用数学归纳法、递推关系、循环求和等方法进行分析。

算法的时间复杂度对于衡量算法的效率非常重要。

较低的时间复杂度意味着算法可以在更短的时间内处理更大规模的问题。

因此,选择合适的算法设计和算法优化可以提高程序的运行效率,并减少资源消耗,对于大规模数据处理和系统性能优化至关重要。

算法分类,时间复杂度,空间复杂度,优化算法

算法分类,时间复杂度,空间复杂度,优化算法

算法分类,时间复杂度,空间复杂度,优化算法算法 今天给⼤家带来⼀篇关于算法排序的分类,算法的时间复杂度,空间复杂度,还有怎么去优化算法的⽂章,喜欢的话,可以关注,有什么问题,可以评论区提问,可以与我私信,有什么好的意见,欢迎提出.前⾔: 算法的复杂度分为时间复杂度与空间复杂度,时间复杂度指执⾏算法需要需要的计算⼯作量,空间复杂度值执⾏算法需要的内存量,可能在运⾏⼀些⼩数据的时候,⼤家体会不到算法的时间与空间带来的体验. 优化算法就是将算法的时间优化到最快,将空间优化到最⼩,假如你写的mod能够将百度游览器的搜索时间提升0.5秒,那都是特别厉害的成绩.本章内容: 1,算法有哪些 2,时间复杂度,空间复杂度 3,优化算法 4,算法实例⼀,算法有哪些 常见的算法有冒泡排序,快排,归并,希尔,插⼊,⼆分法,选择排序,⼴度优先搜索,贪婪算法,这些都是新⼿⼊门必须要了解的,你可以不会,但是你必须要知道他是怎么做到的,原理是什么,今天就给⼤家讲⼀讲我们常⽤的冒泡排序,选择排序,这两个排序算法,1,冒泡排序(Bubble Sort), 为什么叫他冒泡排序呢? 因为他就像是从海底往海⾯升起的⽓泡⼀样,从⼩到⼤,将要排序的数从⼩到⼤排序,冒泡的原理: 他会⼀次⽐较两个数字,如果他们的顺序错误,就将其调换位置,如果排序正确的话,就⽐较下⼀个,然后重复的进⾏,直到⽐较完毕,这个算法的名字也是这样由来的,越⼤的数字,就会慢慢的'浮'到最顶端. 好了该上代码了,下⾯就是冒泡排序的代码,冒泡相对于其他的排序算法来说,⽐较的简单,⽐较好理解,运算起来也是⽐较迅速的,⽐较稳定,在⼯作中也会经常⽤到,推荐使⽤# 冒泡排序def bubble_sort(alist):n = len(alist)# 循环遍历,找到当前列表中最⼤的数值for i in range(n-1):# 遍历⽆序序列for j in range(n-1-i):# 判断当前节点是否⼤于后续节点,如果⼤于后续节点则对调if alist[j] > alist[j+1]:alist[j], alist[j+1] = alist[j+1], alist[j]if__name__ == '__main__':alist = [12,34,21,56,78,90,87,65,43,21]bubble_sort(alist)print(alist)# 最坏时间复杂度: O(n^2)# 最优时间复杂度: O(n)# # 算法稳定性:稳定2,选择排序(selection sort) 选择排序(selection sort)是⼀种简单直观的排序⽅法, 他的原理是在要排序的数列中找到最⼤或者最⼩的元素,放在列表的起始位置,然后从其他⾥找到第⼆⼤,然后第三⼤,依次排序,依次类,直到排完, 选择排序的优点是数据移动, 在排序中,每个元素交换时,⾄少有⼀个元素移动,因此N个元素进⾏排序,就会移动 1--N 次,在所有依靠移动元素来排序的算法中,选择排序是⽐较优秀的⼀种选择排序时间复杂度与稳定性:最优时间复杂度: O(n2)最坏时间复杂度:O(n2)算法稳定性 :不稳定(考虑每次升序选择最⼤的时候)# if alist[j] < alist[min_index]:# min_index = j## # 判断min_index索引是否相同,不相同,做数值交换# if i != min_index:# alist[i],alist[min_index] = alist[min_index],alist[i]### if __name__ == '__main__':# alist = [12,34,56,78,90,87,65,43,21]# # alist = [1,2,3,4,5,6,7,8,9]# select_sort(alist)# print(alist)# O(n^2)# 不稳定def select_sort(alist):"""选择排序"""n = len(alist)for i in range(n - 1):min_index = i # 最⼩值位置索引、下标for j in range(i+1, n):if alist[j] < alist[min_index]:min_index = j# 判断min_index ,如果和初始值不相同,作数值交换if min_index != i:alist[i], alist[min_index] = alist[min_index],alist[i]if__name__ == '__main__':alist = [8,10,15,30,25,90,66,2,999]select_sort(alist)print(alist)这是⼀些算法的时间复杂度与稳定性时间复杂度,空间复杂度 接下来就要来说说时间复杂度与空间复杂度: 时间复杂度就是假如你泡茶,从开始泡,到你喝完茶,⼀共⽤了多长时间,你中间要执⾏很多步骤,取茶叶,烧⽔,上厕所,接电话,这些都是要花时间的,在算法中,时间复杂度分为 O(1)最快 , O(nn)最慢,O(1) < O(logn) <O(n)<O(n2)<O(n3)<O(2n) <O(nn) ⼀般游览器的速度都在O(n),做我们这⼀⾏,要注意客户体验,如果你程序的运⾏特别慢,估计别⼈来⼀次,以后再也不会来了下⾯给⼤家找了张如何计算时间复杂度的图⽚: 空间复杂度(space complexity) ,执⾏时所需要占的储存空间,记做 s(n)=O(f(n)),其中n是为算法的⼤⼩, 空间复杂度绝对是效率的杀⼿,曾经看过⼀遍⽤插⼊算法的代码,来解释空间复杂度的,觉得特别厉害,我就⽐较low了,只能给⼤家简单的总结⼀下我遇到的空间复杂度了, ⼀般来说,算法的空间复杂度值得是辅助空间,⽐如:⼀组数字,时间复杂度O(n),⼆维数组a[n][m] :那么他的空间复杂度就是O(n*m) ,因为变量的内存是⾃动分配的,第⼀个的定义是循环⾥⾯的,所以是n*O(1) ,如果第⼆个循环在外边,那么就是1*O(1) ,这⾥也只是⼀个了解性的东西,如果你的⼯作中很少⽤到,那么没有必要深究,因为⽤的真的很少优化算法这边带来了代码,你们在复制下来了python上运⾏⼀下,看⼀下⽤的时间与不同, ⾃然就懂了,这是未优化的算法''已知有a,b,c三个数,都是0-1000之内的数,且: a+b+c=1000 ⽽且 a**2+b**2=c**2 ,求a,b,c⼀共有多少种组合'''# 在这⾥加⼀个时间模块,待会好计算出结果import time# 记录开头时间start_time=time.time()# 把a,b,c循环出来for a in range(1001):for b in range(1001):for c in range(100):# 判断他主公式第⼀次,并未优化if a+b+c==1000 and a**2 + b**2 == c**2 :# 打印print("a=" ,a)print("b=" ,b)print("c=" ,c)else:passstop_time = time.time()print('⼀共耗时: %f'%(stop_time-start_time))# ⼀共耗时 156.875001秒这是第⼀次优化import time# 记录开头时间start_time=time.time()# 把a,b,c循环出来for a in range(1001):# 这⾥改成1001-a之后,他就不⽤再循环b了for b in range(1001-a):for c in range(100):# 判断他主公式第⼆次,优化了b,if a+b+c==1000 and a**2 + b**2 == c**2 :print("a=" ,a)print("b=" ,b)print("c=" ,c)else:passstop_time = time.time()print('⼀共耗时: %f'%(stop_time-start_time))# ⼀共耗时 50.557070秒最后⼀次优化import time# 记录开头时间start_time=time.time()# 把a,b,c循环出来for a in range(1001):for b in range(1001-a):c=1000 - a - b# 判断他主公式第三次,优化了b和cif a+b+c==1000 and a**2 + b**2 == c**2 :print("a=" ,a)print("b=" ,b)print("c=" ,c)else:passstop_time = time.time()print('⼀共耗时: %f'%(stop_time-start_time))# ⼀共耗时 2.551449秒从156秒优化到l2秒, 基本运算总数 * 基本运算耗时 = 运算时间这之间的耗时和你的机器有着很⼤的关系今天是12⽉30⽇,明天就要跨年了,祝⼤家2019年事业有成,⼯资直线上升,早⽇脱单,。

算法时间复杂度的计算公式

算法时间复杂度的计算公式

算法时间复杂度的计算公式算法时间复杂度是算法效率的一种度量方式,通常用大O符号来表示,例如O(1)、O(n)、O(n^2)等。

在计算算法时间复杂度时,需要考虑算法中各种操作的时间复杂度,并将它们合并为总时间复杂度。

以下是常见的算法操作时间复杂度:1. 常数级别:O(1)2. 对数级别:O(logn)3. 线性级别:O(n)4. 线性对数级别:O(nlogn)5. 平方级别:O(n^2)6. 立方级别:O(n^3)7. 指数级别:O(2^n)计算总时间复杂度的公式如下:1. 顺序执行的操作,时间复杂度直接相加。

例如,若有操作A、B、C,它们的时间复杂度分别为O(a)、O(b)、O(c),则总时间复杂度为O(a + b + c)。

2. 嵌套执行的操作,时间复杂度取最大值。

例如,若有操作A、B,操作A执行了n次,每次的时间复杂度为O(n),操作B的时间复杂度为O(nlogn),则总时间复杂度为O(n*nlogn),即O(n^2logn)。

3. 分支语句的时间复杂度为其中时间复杂度最大的分支的时间复杂度。

例如,若有分支语句,分别包含操作A和操作B,它们的时间复杂度分别为O(a)、O(b),则分支语句的时间复杂度为O(max(a,b))。

4. 循环结构的时间复杂度为循环次数乘以循环体的时间复杂度。

例如,若有循环结构,循环次数为n,循环体包含操作A和操作B,它们的时间复杂度分别为O(a)、O(b),则循环结构的时间复杂度为O(n*max(a,b))。

综上所述,计算算法总时间复杂度需要考虑各个操作的时间复杂度以及它们的执行顺序、嵌套关系、分支和循环结构。

算法时间复杂度的计算公式

算法时间复杂度的计算公式

算法时间复杂度的计算公式
算法时间复杂度是衡量算法效率的重要指标,它是指算法运行时间随着问题规模的增大而增长的速度。

计算算法时间复杂度需要考虑以下几个因素:
1. 循环结构的次数:算法中循环结构执行的次数是影响时间复杂度的重要因素之一。

2. 嵌套循环结构:如果算法中有多个嵌套循环结构,那么时间复杂度的计算就要考虑这些循环的嵌套次数。

3. 条件判断语句:如果算法中有条件判断语句,那么时间复杂度的计算需要根据条件的判断次数进行计算。

4. 递归调用:如果算法中有递归调用,那么时间复杂度的计算需要根据递归的次数进行计算。

算法时间复杂度的计算公式可以表示为:
T(n) = O(f(n))
其中,T(n)表示算法的时间复杂度,f(n)表示算法执行的时间,O表示算法的渐进时间复杂度。

根据算法的实际情况,可以通过分析算法中循环结构的次数、嵌套次数、条件判断次数、递归次数等因素,来确定算法的时间复杂度。

- 1 -。

数据结构算法时间复杂度的计算

数据结构算法时间复杂度的计算

数据结构算法时间复杂度的计算数据结构和算法时间复杂度的计算是评估算法性能的重要手段之一,通过分析算法的时间复杂度,可以了解算法在处理不同规模的输入时所需的时间。

时间复杂度是用来衡量算法执行时间随输入规模增长的趋势。

它通常用大O表示法来表示,表示算法执行时间的增长速度。

大O表示法中的O 表示"上界",即理想情况下算法的最高执行时间。

在计算时间复杂度时,我们关注算法中的基本操作数,而不是具体的执行时间。

例如,对于一个循环结构,我们关注循环体内的操作次数,而不是循环的执行时间。

下面我们将分别介绍几种常见的数据结构和算法以及它们的时间复杂度计算方法。

1. 数组(Array)数组是最简单、最常见的一种数据结构。

数组由一系列相同类型的元素组成,可以通过索引来访问和修改元素。

对于数组来说,可以通过索引直接访问任何一个元素。

所以数组的访问时间复杂度为O(1)。

2. 链表(Linked List)链表是另一种常见的数据结构,它由一系列节点组成。

节点包含了数据和指向下一个节点的指针。

对于链表来说,需要遍历整个链表来访问或者修改一些节点,所以链表的访问时间复杂度为O(n),其中n是链表的长度。

3. 栈(Stack)和队列(Queue)栈和队列是两种常见的线性数据结构。

对于栈来说,只能从栈顶插入和删除元素,所以栈的插入和删除操作的时间复杂度都是O(1)。

对于队列来说,只能从队列的一端插入元素,从队列的另一端删除元素。

队列的插入和删除操作的时间复杂度也都是O(1)。

4. 散列表(Hash Table)散列表通过将关键字映射为数组的索引,然后将值存储在该索引对应的数组位置上。

对于散列表来说,如果散列函数很好的均匀分布关键字,则散列表的插入、删除和查找操作的时间复杂度都是O(1)。

5. 树(Tree)树是一种非线性数据结构,由节点和边组成。

对于树来说,树的操作通常需要遍历整棵树来完成,所以树的插入、删除和查找操作的时间复杂度都是O(n),其中n是树的节点数。

算法的时间复杂度和空间复杂度简单理解

算法的时间复杂度和空间复杂度简单理解

算法的时间复杂度和空间复杂度简单理解时间复杂度是指执⾏算法所需要的计算⼯作量;⽽空间复杂度是指执⾏这个算法所需要的内存空间。

(算法的复杂性体现在运⾏该算法时的计算机所需资源的多少上,计算机资源最重要的是时间和空间(即寄存器)资源,因此复杂度分为时间和空间复杂度在描述算法复杂度时,经常⽤到o(1), o(n), o(logn), o(nlogn)来表⽰对应算法的时间复杂度。

这⾥进⾏归纳⼀下它们代表的含义:这是算法的时空复杂度的表⽰。

不仅仅⽤于表⽰时间复杂度,也⽤于表⽰空间复杂度。

⼀个算法的优劣主要从算法的所需时间和所占⽤的空间两个⽅⾯衡量。

⼀般空间利⽤率⼩的,所需时间相对较长。

所以性能优化策略⾥⾯经常听到空间换时间,时间换空间这样说法 O后⾯的括号中有⼀个函数,指明某个算法的耗时/耗空间与数据增长量之间的关系。

其中的n代表输⼊数据的量。

1. ⽐如时间复杂度为O(n),就代表数据量增⼤⼏倍,耗时也增⼤⼏倍。

⽐如常见的遍历算法。

int x=1; while (x <n){ x++; } list.contains()⽅法,系统会对list中的每个元素e调⽤o.equals(e),因此⽤时间复杂度表⽰是O(n) 该算法执⾏次数是如果n=10, 执⾏次数就是10,n是个变量,⽤时间复杂度表⽰是O(n)。

2. 再⽐如时间复杂度O(n^2),就代表数据量增⼤n倍时,耗时增⼤n的平⽅倍,这是⽐线性更⾼的时间复杂度。

⽐如冒泡排序,就是典型的O(n^2)的算法,对n个数排序,需要扫描n×n次。

for (i = 0; i < n; i++){ for (j = 0; j < n; j++){ //... } } 如果两层循环,该算法for循环,最外层循环每执⾏⼀次,内层循环都要执⾏n次,执⾏次数是根据n所决定的,最⼤时间复杂度是O(n^2),如果内层循环在某种场景⼀次就跳出,其实也可以退化成o(n), 通常我们计算时间复杂度都是计算最多情况.由此类推,如果是三层循环,最⼤时间复杂度就是 O(n^3).⽐如冒泡、选择等等 3. O(1)就是最低的时空复杂度了,也就是耗时/耗空间与输⼊数据⼤⼩⽆关,⽆论输⼊数据增⼤多少倍,耗时/耗空间都不变。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

7 then largest ← r
//与右孩子比较,不满足堆的条件
8 if largest ≠ i
9 then {exchange A[i] ↔ A[largest]
10
MAX-HEAPIFY(A, largest)
}
每层比较2次,整理时间与i的高度成正比。
整理堆的实例
有n个节点的堆,最大整理时间为 2 log n。 粗略分析建堆的时间为 n log n,但似乎太不精确了。
只能在规模为n的某些或某类有代表性的合法输 入中统计相应的ei , i=1,2,…,k,评价时间复杂 性。
一般只考虑三种情况下的时间复杂性,即最坏情况、最好情况和平均 情况下的时间复杂性,井分别记为:
W(n) = max{ T(n,I) } , I∈Dn B(n) = min { T(n,I) }, I∈Dn A(n)=∑P( I )T(n,I) I∈Dn
flag ←0
/*发生了交换*/
} if flag then beak
/* 没有交换,排序结束*/
}
enddo
如果将if a[j]<a[j+1] then {….. }当做一个元运算,花的时间为C
当输入的数据已经排好序,做了n-1次元运算; 当输入的数据是增序,则需要做n(n-1)/2次元运算。
显然,不可能对规模n的每一种合法的输入I都去 统计ei(n,I),i=1,2,…,k。因此T(n,I)的表达式还 得进一步简化。
k
T (N , I ) ti.ei (N.I ) i 1
其中ti,i=1,2,..,k,是与N,I无关 的常数。
先看一个实例:
改进冒泡如排序算法的基本步骤如下:
for i ←1 to n-1 do
{flag ←1
for j ←1 to n-i do
if a[j]<a[j+1] then {交换a[j]、a[j+1]
考察实例的
建堆过程,
总体比较时间 为所有节点的 整理时间之和, 各层上的节点 的整理时间是 相同的。
BUILD-MAX-HEAP(A)
else U← m-1 }
规则7
对于break语句。为了便于表达从循环体的中途跳转到循环 体的结束,引入break 语句。在时间复杂性分析时可以假设 它不需要任何额外的时间。
规则8 对于过程调用和函数调用语句,它们需要的时间包括两部分,
一部分用于实现控制转移,另一部分用于执行过程(或函 数)本身,这时可以根7)进行分析,一层一层地剥,直到计算出 最外层的运行时间便是所求。
如果过程(或函数)出现直接或间接的递归调用,则根据过程(或函数)的内涵建 立起这些待定函数之间的递归关系得到递归方程。最后用求递归方程解 的渐进阶的方法确定最坏情况下的复杂性的渐进阶。
经验和技巧是非常重要的
例:建最大堆算法的复杂性分析
BUILD-MAX-HEAP(A) 1 heap-size[A] ← length[A] 2 for i ← ⌊length[A]/2⌋ downto 1 n/2次 3 do MAX-HEAPIFY(A, i) 归结到分析 MAX-HEAPIFY(A, i)的时间
Dn是规模为n的合法输入的集合,P(I)是在算法的应用中 出现输入I 的概率。
最具有可操作性和实际价值的是最坏情况下的时间复杂 性。我们对算法的时间复杂性分析的兴趣主要将放在W(n) 上。没有特殊说明时,T(n)一般指的就是W(n)。
2.2.1算法时间复杂性计量
对于同一类问题,采用这类算法的基本运算次数作为算法的运算时间。 例如:
MAX-HEAPIFY(A, i)
1 l ← LEFT(i)
2 r ← RIGHT(i)
3 if l ≤ heap-size[A] and A[l] > A[i ] //与左孩子比较,不满足堆的条件
4 then largest ← l
//记下较大者的下标
5 else largest ← i
6 if r ≤ heap-size[A] and A[r] > A[largest]
“汉诺塔”算法的基本运算是圆盘的移动; 比较排序算法,用算法所用的比较次数作为该类算法的 运算时间; 矩阵相乘:基本运算是两个数的相乘; 树的搜索:基本运算是节点的访问; 图的算法:节点和边的运算。
2.2.2 时间复杂性的计算规则
分析时间复杂性渐近阶的8条规则 : 规则1:
赋值、比较、算术运算、逻辑运算、读写单个常量 或单个变量等,只需要1个单位时间。 规则2 条件语句"if C then S1 else S2"需要Tc+max(Ts1,Ts2)的 时 和间Ts2,分其别中是T执c是行计语算句条S1件和表S达2需式要C的需时要间的。时间,而Ts1 规则3 选择语句"Case A a1:S1; a2:S2; … ;am:Sm; end", 需要max(Ts1, Ts2,…,Tsm)的时间,其中Tsi是执行语 句Si所需要的时间,i=l,2,…,m。
规则6与规则5不同,循环次数是隐含的。 例如,b_search函数中的while循环语句。按规
则(1)-(4), while (not found)and(U≥=L)
{m←(U+L) div 2 if c=A[m] then found←true else if c>A[m] then L← I+1
规则4
访问一个数组的单个分量或一个记录的单个域, 只需要1个单位时间。
规则5
执行一个for循环语句需要的时间等于执行该循 环体所需要的时间乘上循环的次数。
规则6
执行一个while循环语句“while C do S”,需要 的时间等于
(计算条件表达式C的时间+执行循环S体的时间)* 循环的次数。
2.1时间复杂性函数
T(N,I) 是算法在一台抽象的计算机上运行所需的时间。 设此抽象的计算机所提供的元运算有k种,他们分别 记为O1,O2 ,..,Ok;设这些元运算每执行一次所需要 的时间分别为t1,t2,..,tk 。
对于给定的算法A,用到元运算Oi的次数为ei, i=1,2,..,k ,很明显,对于每一个i, ei是n和I的函数, 即ei=ei(n,I)。那么有:
相关文档
最新文档