一、如何分析、统计算法的执行效率和资源消耗
时间、空间复杂度分析——来衡量算法代码的执行效率。
为什么需要复杂度分析?
事后统计法(把代码跑一遍,通过统计、监控,就能得到算法执行的时间和占用的内存大小)有非常大的局限性:
1、测试结果非常依赖测试环境
不同的处理器运行一样的代码,比如同一段代码i9处理器肯定比i3处理器执行速度快;但是不一样的代码在不同的机器运行结果可能截然不同,比如原本在一台机器上a代码比b代码运行速度快,但是换到另外一台机器上,结果可能就相反了。
2、测试结果受数据规模的影响大
对同一个排序算法,待排序数据的有序度不一样,排序的执行时间就会有很大的差别。极端情况下,如果数据已经是有序的,那排序算法不需要做任何操作,执行时间就会非常短。除此之外,如果测试数据规模太小,测试结果可能无法真实地反应算法的性能。比如,对于小规模的数据排序,插入排序可能反倒会比快速排序要快!
所以,需要一个不用具体的测试数据来测试,就可以粗略地估计算法的执行效率的方法。
大O复杂度表示法
下面的代码,求1、2、3…n的累加和。估算一下代码的执行时间。
int cal(int n) {
int sum = 0;
int i = 1;
for (; i <= n; ++i) {
sum = sum + i;
}
return sum;
}
从 CPU 的角度来看,这段代码的每一行都执行着类似的操作:读数据-运算-写数据。尽管每行代码对应的 CPU 执行的个数、执行的时间都不一样,但是,这里只是粗略估计,所以可以假设每行代码执行的时间都一样,为 unit_time。在这个假设的基础之上,这段代码的总执行时间是多少呢?
第 2、3 行代码分别需要 1 个 unit_time 的执行时间,第 4、5 行都运行了 n 遍,所以需要 2n*unit_time 的执行时间,所以这段代码总的执行时间就是 (2n+2)*unit_time。可以看出来,所有代码的执行时间 T(n) 与每行代码的执行次数成正比。
以同样的思路再来分析下面的代码
int cal(int n) {
int sum = 0;
int i = 1;
int j = 1;
for (; i <= n; ++i) {
j = 1;
for