1. 算法效率的度量
(1)事后统计法
①通过设计好的测试程序和数据,比较不同算法对同一组输入数据的运行处理时间
②主要缺陷
A.为了获得不同算法的运行时间,必须编写好测试程序
B.运行时间严重依赖硬件以及运行时的环境因素
C.算法的测试数据选取和设计困难,并且程序的运行时间往往还与测试数据的规模有关。效率高的算法在小的测试数据面前往往得不到体现。
(2)事前分析估算
①依据统计的方法对算法效率进行估算
②影响算法效率的主要因素
A.算法采用的策略和方法(这是算法好坏的根本)
B.问题的输入规模(指的是输入量的多少)
C.编译产生的代码质量(由软件来支持)
D.机器执行指令的速度(看硬件性能)
2. 算法效率的估计
(1)简单估算1:
(2)简单估算2:
(3)简单估算3:
(4)启示
①三种求和算法中关键部分的操作数量分别为2n、n和1
②随着问题规模n的增大,它们操作数量的差异会越来越大,因此实际算法在效率上的差异也会变得非常明显!
【实例分析】程序效率估算
#include <iostream> using namespace std; int func(int a[], int len) // ==>(n*n + 2) { int ret = 0; //1 for(int i=0; i<len; i++) { for(int j=0; j<len; j++) { //程序关键部分的操作数量为n*n ret += a[i] * a[j]; //n * n } } return ret; //1 } int main() { int array[] = {1, 2, 3, 4, 5}; cout << func(array, 5) << endl; //255 return 0; }
3. 函数的渐近增长
(1)算法操作数据对比1
次数 |
A(4n+8) |
A´(n) |
B(2n2+1) |
B´(n2) |
n=1 |
12 |
1 |
3 |
1 |
n=2 |
16 |
2 |
9 |
4 |
n=3 |
20 |
3 |
19 |
9 |
n=10 |
48 |
10 |
201 |
100 |
n=100 |
408 |
100 |
20001 |
10000 |
n=100 |
4008 |
1000 |
2000001 |
1000000 |
【结论】
①n<=3时,算法B(2n2+1)优于算法A(4n+8)
②当n越来越大的时候,算法A(4n+8)相对算法B(2n2+1)的优势明显
(2)算法操作数量的对比2
次数 |
C(2n2+3n+1) |
C(n2) |
D(2n3+3n+1) |
D(n3) |
n=1 |
6 |
1 |
6 |
1 |
n=2 |
15 |
4 |
23 |
8 |
n=3 |
28 |
9 |
64 |
27 |
n=10 |
231 |
100 |
2031 |
1000 |
n=100 |
20301 |
10000 |
2000301 |
100000 |
【结论】
①n==1时,算法C(2n2+3n+1)和算法D(2n3+3n+1)的操作数量相同。
②当n越来越大的时候,算法C(2n2+3n+1)的效率远高于算法D(2n3+3n+1)。
(3)算法操作数量的对比3
次数 |
E(2n2) |
F(3n+1) |
G(2n2+3n+1) |
n=1 |
2 |
4 |
6 |
n=2 |
8 |
7 |
15 |
n=5 |
50 |
16 |
66 |
n=100 |
20000 |
301 |
20301 |
n=10000 |
200000000 |
30001 |
200030001 |
n=100000 |
20000000000 |
300001 |
20000300001 |
n=1000000 |
2000000000000 |
3000001 |
2000003000001 |
【结论】
①判断一个算法的效率时,操作数量中的常数项和其他次要项常常可以忽略,只需要关注主项(最高阶项)就能得出结论。
②判断一个算法的好坏,只通过少量的数据是不能做出准确判断的。随着问题规模n的增大,某个算法会越来越优于另一个算法,或越来越差于另一个算法。这就是事前估算方法的理论依据。
4. 小结
(1)算法的度量有事后统计法和事前分析估算法
(2)事后统计法不容易准确度量算法的效率
(3)事前分析估算法通过操作数量度量算法效率
(4)判断一个算法效率时,只需关注最高阶项就能得出结论
(5)某个算法,随着问题规模n的增大,它会越来越优于另一算法,或者越来越差于另一算法。