1.选用的算法应该是正确的(算法的正确性不在此论述)。除此之外,通常有三个方面的考虑:
(1)算法在执行过程中所消耗的时间;
(2)算法在执行过程中所占资源的大小,例如,占用内存空间的大小;
(3)算法的易理解性、易实现性和易验证性等等。
2.一个算法在执行过程中所消耗的时间取决于下面的因素:
(1)算法所需数据输入的时间;
(2)算法编译为可执行程序的时间;
(3)计算机执行每条指令所需的时间;
(4)算法语句重复执行的次数。
其中(1)依赖于输入设备的性能,若是脱机输入,则输入数据的时间可以忽略不计。(2)(3)取决于计算机本身执行的速度和编译程序的性能。因此,习惯上将算法语句重复执行的次数作为算法的时间量度。
下面给出2个执行次数计算较为精确的例子。
上面的程序段执行次数为2n+3次。再看下面矩阵相加的例子。
矩阵相加的执行次数为2n^2+2n+2。
一般情况下,n为问题规模(大小)的量度,如数组的长度、矩阵的阶、图中的顶点数等等。
对于前面add函数来说,问题规模量度为常数(1);对于数组排序问题来说,问题规模量度为输入数组的长度(记为n);对于n阶矩阵相加来说,问题规模量度为矩阵阶数的平方(记为n^2)。
为了给出算法通用的时间量度,用数学概念来描述算法的执行次数,可以把一个算法中语句的执行次数称为语句频度或时间频度,记为T(n)。当问题规模n不断变化时,时间频度T(n)也会不断变化,我们需要评估当n不断变化时,时间频度T(n)的变化规律。
若有某个辅助函数f(n),当n趋向于无穷大时,如果T(n)/ f(n)的极限为不等于零的常数,则认为T(n)与f(n)是同量级的函数,记作:T(n) =O(f(n)),O(f(n))称为算法的渐进时间复杂度,简称时间复杂度。
渐进时间复杂度表示的意义是:
(1)在较复杂的算法中,进行精确分析是非常复杂的;
(2)一般来说,我们并不关心T(n)的精确度量,而只是关心其量级。
T (n) = O(f (n)) 表示存在一个常数C,当n趋于正无穷大时,总有T (n) ≤ C * f(n),其意义是T(n)在n趋于正无穷大时跟f(n)基本接近,因此完全可以用f(n)来表示T(n)。
O(f (n))通常取执行次数中最高次方或最大指数部分的项。例如:
(1)阵列元素相加为2n+3 = O(n)
(2)矩阵相加为2n^2+2n+1 = O(n^2)
(3)矩阵相乘为2n^3+4n^2+2n+2 = O(n^3)
在各种不同的算法中,若算法语句的执行次数为常数,则算法的时间复杂度为O(1),按数量级递增排列,常见的时间复杂度量有:
(1)O(1):常量阶,运行时间为常量
(2)O(logn):对数阶,如二分搜索算法
(3)O(n):线性阶,如n个数内找最大值
(4)O(nlogn):对数阶,如快速排序算法
(5)O(n^2):平方阶,如选择排序,冒泡排序
(6)O(n^3):立方阶,如两个n阶矩阵的乘法运算
(7)O(2^n):指数阶,如n个元素集合的所有子集的算法
(8)O(n!):阶乘阶,如n个元素全部排列的算法
评估算法时间复杂度的具体步骤是:
(1)找出算法中重复执行次数最多的语句的频度来估算算法的时间复杂度;
(2)保留算法的最高次幂,忽略所有低次幂和高次幂的系数;
(3)将算法执行次数的数量级放入大Ο记号中。