一 概述
- 对于同一个问题,可以有许多种不同的算法。究竟如何来评价这些算法的优劣程度呢?
- 算法分析的目的是看算法实际是否可行,并在同一问题存在多的算法时可进行性能上的比较,以便从中挑选比较优的算法
- 一个好的算法首先要具备正确性,然后是健壮性,可读性,在几个方面都满足的情况下,主要考虑算法的效率,通过算法的效率来评判不同算法的优劣程度。
二 算法效率的评价指标
算法效率以下两个方面来考虑
- 时间效率:指的是算法所耗费的时间
- 空间效率:指的是算法执行过程中所耗费的存储空间
时间效率和空间效率有时候是矛盾的
三 时间效率和空间效率的度量
3.1 算法时间效率的度量
如何度量
算法时间效率可以用依据算法编制的程序在计算机上执行所消耗的时间来度量
两种度量方法
事后统计
- 将算法实现,测算其时间和空间开销
- 缺点:编写程序实现算法将花费较多的时间和精力;所得实验结果依赖于计算机的软硬件等环境因素,掩盖算法本身的优劣
事前分析
- 对算法所消耗资源的一种估算方法
四 事前分析方法
4.1 算法运行时间
一个算法的运行时间是指一个算法在计算机上运行所消耗的时间大致可以等于计算机执行一种简单的操作(如赋值、比较、移动等)所需的时间与算法中进行的简单操作次数乘积
算法运行时间=一个简单操作所需的时间x简单操作次数
也即算法中每条语句的执行时间之和
算法运行时间=∑ 每条语句的执行次数x该语句执行一次所需的时间
说明: 每条语句的执行次数又称为语句频度
算法运行时间=∑ 语句频度x该语句执行一次所需的时间
每条语句执行一次所需的时间,一般是随机器而已的。取决于机器的指令性能、速度以及编译的代码质量。是由机器本身软硬件环境决定的,它与算法无关。
所以,我们可假设执行每条语句所需的时间均为单位时间。此时对算法的运行时间的讨论就可转化为讨论该算法中所有语句的执行次数,即频度之和了
这就可以独立不同机器的软硬件环境来分析算法的时间性能了
4.2 示例:两个nxn矩阵相乘的算法可描述为
for(i=1;i<=n;i++) //n+1次
{
for(j=1;i<=n;j++) //n(n+1)次
{
c[i][j]=0; //n*n次
for(k=0;k<n;k++) //n*n*(n+1)次
{
c[i][j]=c[i][j]+a[i][k]*b[k][j]; //n*n*n次
}
}
}
我们把算法所耗费的时间定义为该算法中每条语句的频度之和,则上述算法的时间消耗T(n)为
T(n)=2n^3+3n^2+2n+1
为了便于比较两个不同算法的时间效率,我们仅比较它们的数量级
例如:两个不同的算法,时间消耗分别是:
T1(n)=10n^2 与 T2(n)=5n3
若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n))为算法的渐进时间复杂度(O是数量级的符号),简称时间复杂度
对于求解矩阵相乘问题,算法耗费时间
T(n)=2n^3+3n^2+2n+1
n->∞时,T(n)/n^3 ->2,这表示n充分大时,T(n)与n^3是同阶或同数量级,引入大O
记号,则T(n)可记作
T(n)=O(n^3)
4.3 渐近时间复杂度
T(n)=O(n^3),这就是求解矩阵相乘问题的算法的渐进时间复杂度
一般情况下,不必计算所有操作的执行次数,而只考虑算法中的基本操作执行的次数,它是问题规模n的某个函数,用T(n)表示
算法中基本语句重复执行的次数是问题规模n的某个函数f(n),算法的时间量度记作:T(n)=O(f(n))
它表示随着n的增大,算法执行的时间的增长率和f(n)的增长率相同,称渐近时间复杂度
数学符号“O”的定义为:
- 若T(n)和f(n)是定义在正整数集合上的两个函数,则T(n)=O(f(n))表示存在正的常数C和n0,使得当n>=n0时都满足0<=T(n)<=Cf(n)
4.4 总结
算法中基本语句重复执行的次数是问题规模n的某个函数f(n),算法的时间量度记作:T(n)=O(f(n))
- 算法中重复执行次数和算法的执行时间成正比的语句
- 对算法运行时间的贡献最大
- 执行次数最多
n越大算法的执行时间越长
- 排序:n为记录数
- 矩阵:n为矩阵的阶数
- 多项式:n为多项式的项数
- 集合:n为元素个数
- 树:n为树的节点个数
- 图:n为图的顶点数或边数