注意:本文摘自《数据结构——从概念到C实现》【王红梅 皮德常 编著】
目录
算法效率分析
度量算法的效率有两种方法
一,事后统计,先实现算法,再输入数据来测量其时间,空间开销。此种方法的缺点至少有
- 编写程序实现算法很耗费时间精力
- 实验结果依赖于计算机的软硬件等环境因素,有时很容易掩盖算法本身的优劣。
二,事前分析估计,渐进复杂度估算,这是对算法所消耗资源的一种估算方法。
算法的时间复杂度
同一个算法用不同的程序设计语言实现,或者用不同的编译程序进行编译,或者在不同的计算机上运行,效率均不相同。撇开与计算机软硬件有关的因素,影响算法时间代价的最主要因素是问题规模。问题规模是指输入量的多少,一般来说,它可以从问题的描述中得到。例如,找出100以内的所有素数,问题规模是100;对一个具有n个整数的数组进行排序,问题规模是n。一个显而易见的事实是:几乎任何算法对于规模更大的输入需要运行更长的时间。例如,找出1000内所有的素数比找出100内所有的素数需要更多的时间。所以,运行算法所需要的时间T是问题规模n的函数,记作T(n)。
要精确地表示算法的运行时间函数常常是很困难的,即使能够给出,也可能是个相当复杂的函数。为了客观地反映一个算法的执行时间,可以用算法中基本语句的执行次数来度量算法的工作量。基本语句是执行次数与整个算法的执行次数成正比的语句,基本语句对算法运行时间的贡献最大,是算法中最重要的操作。这种衡量效率的方法得出的不是时间量,而是一种增长趋势的度量。换而言之,只考察问题规模充分大时,算法中基本语句的执行次数在渐近意义下的阶,称作算法的渐近时间复杂度,通常使用大O记号表示。
【定义1-1】若存在两个正的常数c和n0,对于任意的n>=n0,都有T(n)<=c * f(n),则称T(n) = O(f(n))(读作“T(n)是Ofn的”,f(n)即与算法的运行时间函数同一数量级的估算函数)
此定义表明了函数T(n)与f(n)具有相同的增长趋势,并且T(n)的增长至多趋同于函数f(n)的增长。大O记号用来描述增长率的上限,也就是说,当输入规模为n时,算法耗费的时间的最大值。
算法的时间复杂度实际上是一种估算技术,若两个算法中的一个比另一个“稍微快一点”时,并不能基于时间复杂度来判断哪个算法更为优越。但在实际应用中,基于时间复杂度来判断算法的效率被证明是很有效的,尤其在确定算法是否值得实现的时候。常见的时间复杂度如下:
算法的时间复杂度是衡量一个算法优劣的重要标准。一般而言,具有多项式时间复杂度的算法是可以接受的,可使用的算法,而具有指数时间复杂度的算法,仅当问题规模足够小的时候才是可以使用的算法。
算法的空间复杂度
算法在运行过程中所需的存储空间包括:
- 输入/输出数据占用的空间
- 算法本身占用的空间
- 执行算法所需要的辅助空间
其中,输入/输出数据占用的空间取决于问题,与算法无关;算法本身占用的空间虽然与算法相关,但一般其大小是固定的。所以,算法的空间复杂度是指算法在执行过程中需要的辅助空间数量,也就是除算法本身和输入输出数据所占用的空间外,算法临时开辟出的存储空间。
如果算法所需的辅助空间相对于问题规模来说是一个常数,我们称此算法为原地(或就地)工作,否则,这个辅助空间数量应该是问题规模的函数,通常记作:
其中,n为问题规模,分析方法与算法的时间复杂度类似。