如何衡量一个算法的优劣?
一、事后统计的方法
简言之就是先让程序在电脑上跑一下,在旁边弄一个计时器进行计数,这样它到底运行了多长时间我们就知道了,这种方法可行,我们可以知道运行了多久,但是问题是同一个程序在计算机上运行时,运行同一个程序,执行同一个任务,它占用的时间实际上和计算机当时的很多状况有关系,比如计算机当时的内存占用情况,还有当时CPU的占用情况,等等,甚至还和这台计算机本身有很大的关系,因此,用这种事后统计的方法实际上是不可行的。
二、事前分析估算的方法
事前分析估算的方法,简言之,就是当我们的算法写好以后,我们人为的去估算这个算法所需要的时间。那么事前估算的话我们肯定是估算不了的,因为在不同的电脑上运行出来,它占用的时间肯定是不一样的。所以如果我们事前估算算法的优劣的话,我们的单位肯定不是时间了,也就是说我们并不是用时间来衡量算法的优劣。那么我们用什么来衡量呢?我们衡量一个算法实际上从两方面,一个是时间复杂度,一个是空间复杂度。简单的说,时间复杂度就是我这个算法在计算的时候它要占用多长时间。那空间复杂度就是说我这个算法在运行的时候需要占用多少内存。我们在运行一个算法的时候,在大多数情况下,当我们在不考虑空间的情况下,大部分的情况下,我们在说这个算法的复杂度的时候,都是在考虑算法的时间复杂度。
语句频度:一个算法中的语句执行次数称为语句频度,记为T(n)。
从上图中可以看出,2n+20和3n+10的区别主要就是2n和3n的区别,常数项可以
忽略。
从上图中可以看出,以上四个函数只有两种走向,主要就是2n^2和n^2
的区别,一次项和常数项则可以省略。
从上图中可以看出,3n^2 和 5n^2
是最下边一条线重合了,n^3和6n^3
都呈现上升的趋势,都在迅速向上走,6n^3
更加倾斜,可以直接看出,以上四个函数其实就是n^2跟n^3
之间的区别。
总结:从以上三幅图中可以看出,各个函数之间其实真正起作用的,是那个对我们函数值影响最大的值。
时间复杂度:一般情况下,算法中的基本操作语句的重复执行次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数,记做T(n)=O(f(n)),称O(f(n))为算法的渐进时间复杂度,简称时间复杂度。
T(n)不同,但时间复杂度可能相同,如:T(n)=n^2+5n+6与T(n)=3n^2+3n+2
,它们的T(n)不同,但时间复杂度相同,都为O(n^2)。
计算时间复杂度的方法:
用常数1代替运行时间中的所有加法常数
修改后的运行次数函数中,只保留最高阶项
去除最高阶项的系数。
平均时间复杂度和最坏时间复杂度:
平均时间复杂度是指所有可能的输入实例均以等概率出现的情况下,该算法的运行时间。
最坏情况下的时间复杂度称最坏时间复杂度,一般讨论的时间复杂度均是最坏情况下的时间复杂度,这样做的原因是;最坏情况下的时间复杂度是算法在任何输入实例上运行时间的界限,这就保证了算法的运行时间不会比最坏情况更长。
空间复杂度:空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))
。比如直接插入排序的时间复杂度O(n^2)
,空间复杂度是O(1) 。而一般的递归算法就要有O(n)的空间复杂度了,因为每次递归都要存储返回信息。一个算法的优劣主要从算法的执行时间和所需要占用的存储空间两个方面衡量。